我有这个:
List<string> list = new List<string>();
list.Add("a-b-c>d");
list.Add("b>c");
list.Add("f>e");
list.Add("f>e-h");
list.Add("a-d>c-b");
我想删除重复项。在这种情况下,重复项是“abc>d”和“ad>cb”。两者都有相同的字符,但顺序不同。我试过:
list.Distinct().ToList();
但是没有用!
看起来你想要:
var distinct = list
.Select((str, idx) => new { Str = str, Idx = idx })
.GroupBy(pair => new HashSet<char>(pair.Str), HashSet<char>.CreateSetComparer())
.Select(grp => grp.OrderBy(p => p.Idx).First())
.ToList();
这将保留第一个元素并删除序列中包含相同字符的任何后续字符串。
您还可以使用Aggregate
来跟踪您已经看到的字符集:
var distinct = list
.Aggregate(new Dictionary<HashSet<char>, string>(HashSet<char>.CreateSetComparer()), (dict, str) =>
{
var set = new HashSet<char>(str);
if (!dict.ContainsKey(set))
dict.Add(set, str);
return dict;
})
.Values
.ToList();
您必须定义一个自定义项IEqualityComparer
,使系统能够理解您何时认为两个字符串“相等”。例如:
List<string> list = new List<string>();
list.Add("a-b-c>d");
list.Add("b>c-d-f");
list.Add("c-d-f>e");
list.Add("a-d>c-b");
var distinctItems = list.Distinct(new KeyFuncEqualityComparer<string>(
s => new String(s.AsEnumerable().OrderBy(c => c).ToArray())));
结果:
a-b-c>d
b>c-d-f
c-d-f>e
...使用这个通用的 IEqualityComparer 实现:
public class KeyFuncEqualityComparer<T> :IEqualityComparer<T>
{
private readonly Func<T, object> _getKey;
public KeyFuncEqualityComparer(Func<T, object> getKey)
{
_getKey = getKey;
}
public bool Equals(T x, T y)
{
return _getKey(x).Equals(_getKey(y));
}
public int GetHashCode(T obj)
{
return _getKey(obj).GetHashCode();
}
}
未经测试
list<int> dups = new list<int>();
for(int i = 0; i < list.count - 1; i++)
{
for(int j = 1; j < list.count; j++)
{
int len = list[j].length;
bool b = false;
for(int k = 0; k < list[i].length; k++)
{
if(k < len && (list[i][k] != list[j][k]))
{
b = false;
break;
}
b = true;
}
if(b == true)
{
dups.add(i);
}
}
}
然后从列表中删除所有重复