Comment #0 by bearophile_hugs — 2014-12-28T01:02:32Z
A pattern in D code is to remove key-value pairs from an associative array according to some given rule.
This pattern:
- Is sufficiently common in D code;
- It's bug prone because iterating an associative array you are removing items from could cause troubles;
- It can be implemented with a simple clear function;
- It's often implemented not efficiently in user cose because sometimes you solve the problem copying all the associative array, with memory-wasting code like:
int[int] aa = ...;
foreach (key; aa.keys)
if (predicate1(key))
aa.remove(key);
foreach (key; aa.keys) {
auto value = aa[key];
if (predicate2(key, value))
aa.remove(key);
}
So I suggest a function named like std.array.removeIf that accepts a predicate with one or two arguments, if the predicate has one argument it receives the key, otherwise it receives both key and value:
aa.removeIf!(key => key > 5);
aa.removeIf!((key, val) => key > val);
(The name of the function doesn't contain "associative array" because later an overload of "removeIf" can be defined for dynamic arrays too).
Comment #1 by greensunny12 — 2018-03-31T16:27:36Z
Not sure whether such one/two-liners would be accepted to Phobos.
---
import std.experimental.all;
auto removeIf(alias pred, AA)(AA aa)
{
aa.byPair.filter!(not!pred).each!(e => aa.remove(e.key));
return aa;
}
void main()
{
auto aa = ["a" : 1, "b" : 2];
aa.removeIf!(a => a.key == "a").writeln;
}
---
But efficiency and bug-proneness are two good points.
Comment #2 by schveiguy — 2019-06-18T23:55:59Z
(In reply to Seb from comment #1)
> auto removeIf(alias pred, AA)(AA aa)
> {
> aa.byPair.filter!(not!pred).each!(e => aa.remove(e.key));
> return aa;
> }
This implementation isn't valid. You can't remove while iterating. You would need to somehow lock the AA from rehashing as you removed items.
Comment #3 by schveiguy — 2019-06-18T23:56:28Z
I think especially if you remove the CURRENT element while iterating you are in for trouble.
Comment #4 by robert.schadek — 2024-12-01T16:23:27Z