如何从Dart列表中删除类似的元素?

Vic*_*aev 3 list elements equivalent dart

我想从飞镖列表中删除相似的元素,这些相似性是由某些布尔函数给出的。例如,在Mathematica中,我将实现以下目标:

Union[{2, -2, 1, 3, 1}, SameTest -> (Abs[#1] == Abs[#2] &)]
Run Code Online (Sandbox Code Playgroud)

该语句产生以下列表-{-2,1,3}。实际上,我想从每个对等类中保留一个元素。

我知道有一个函数list.retainWhere((e)=> bool test(e)),不幸的是,此测试一次只能对一个值进行操作。当然,另一种选择是我可以做这样的事情(只是从脑子里写)

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);
  }  
}
Run Code Online (Sandbox Code Playgroud)

但是我觉得这有点丑。

有什么建议吗?

更新 我将更详细地阐明我的问题,然后说明如何使用下面给出的建议解决问题。

  class Pair<T> {
    final T left;
    final T right;
    Pair(this.left, this.right);    
  }
Run Code Online (Sandbox Code Playgroud)

现在,我想拥有一个包含这样的对或的结构,并且我不想保持彼此足够接近的点。为此我采用亚历山大Ardhuin和他的评论的解决方案也是如此,这实际上使得对于更复杂的情况有所不同:考虑2种元素e1e2您需要定义hashCode,以确保e1.hashCode == e2.hashCode如果e1 == e2

所以就这样:

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 );
Run Code Online (Sandbox Code Playgroud)

结果将是{0.1,0.2}。如果将的第二个元素list更改为{0.1, 0.201}I,则可以预料得到一个包含两个元素的集合。

希望这是有用的。

Ale*_*uin 5

您可以使用LinkedHashSet并定义要使用的等于哈希码

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}
}
Run Code Online (Sandbox Code Playgroud)