I'd like to remove similar elements from a dart list, where similarity is given by some boolean function. For example in Mathematica I would achieve that as follows:
Union[{2, -2, 1, 3, 1}, SameTest -> (Abs[#1] == Abs[#2] &)]
This statement yields the following list - {-2, 1, 3}. Effectively I'd like to keep one element from each equivalence class.
I know there is a function list.retainWhere( (e) => bool test(e) ), unfortunately this test can only operate on one value at a time. Another option, of course, I could do something like this (just writing from my head)
i=0;
for(final E in list) {
i++;
for(j=i; j<list.skip(i).length; j++) {
if sameTest(e, E) then list.removeAt(i+j);
}
}
but i find this bit ugly.
Any advice?
UPDATE I will clarify my problem in more details and then show how to solve it using advice given below.
class Pair<T> {
final T left;
final T right;
Pair(this.left, this.right);
}
Now I want to have a structure holding such pair or points, and i don't want to hold point which are sufficiently close to each other. To do so I adopt solution of Alexandre Ardhuin and his comment too, which actually makes a difference for more complicated cases: Considering 2 elements e1
and e2
you have to define hashCode
to ensure that e1.hashCode == e2.hashCode
if e1 == e2
so here it goes:
int N=1000;
LinkedHashSet<Pair<double>> myset =
new LinkedHashSet<Pair<double>>(
equals: (Pair<double> e1, Pair<double> e2) =>
(e1.left - e2.left)*(e1.left - e2.left) + (e1.right - e2.right)*(e1.right - e2.right) < 1/N,
hashCode: (Pair<double> e){
int ex = (e.left*N).round();
int ey = (e.right*N).round();
return (ex+ey).hashCode;
}
);
List<Pair<double>> list = [new Pair<double>(0.1,0.2), new Pair<double>(0.1,0.2001)];
myset.addAll( list );
the result will be {0.1,0.2}
. If the second element of list
is altered to {0.1, 0.201}
I predictably get a set with two elements.
Hope this was useful.
You can use a LinkedHashSet and define the equals and hashcode to use.
import 'dart:collection';
main() {
final result = new LinkedHashSet<int>(
equals: (int e1, int e2) => e1.abs() == e2.abs(),
hashCode: (int e) => e.abs().hashCode);
result.addAll([2, -2, 1, 3, 1]);
print(result); // {2, 1, 3}
}