Domanda

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.

È stato utile?

Soluzione

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}
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top