4

我正在尝试通过其两个属性过滤对象列表。如果有重复,则可以删除对象。如果第一个属性与第二个属性具有相同的值,并且第二个属性与第一个属性具有相同的值。

例子:

object0: id0=1A, id1=2B
object1: id0=1A, id1=2B
object2: id0=1A, id1=3C
object3: id0=2B, id1=1A
object4: id0=2B, id1=3C
object5: id0=3C, id1=2B

所以会发生以下情况: object0 删除 object1 和 object 3 object4 删除 object5

最终输出:

object0: id0=1A, id1=2B
object2: id0=1A, id1=3C
object4: id0=2B, id1=3C 

现在我有 FOR 循环这样做,但我想知道是否有办法用 linq 做到这一点?我尝试过使用 Distinct、DistinctBy 和 GroupBy。我需要自己比较才能完成吗?

4

2 回答 2

4

这样做。

source
  .GroupBy(x => new {min = Math.Min(x.Id0, x.Id1), max = Math.Max(x.Id0, x.Id1)})
  .Select(g => g.First());

经测试。

    public void SillyTuplesTest()
    {
        List<Tuple<string, int, int>> source = new List<Tuple<string, int, int>>()
        {
            Tuple.Create("object0", 1, 2),
            Tuple.Create("object1",1, 2),
            Tuple.Create("object2",1, 3),
            Tuple.Create("object3",2, 1),
            Tuple.Create("object4",2, 3),
            Tuple.Create("object5",3, 2)
        };

        var result = source
            .GroupBy(x => new { min = Math.Min(x.Item2, x.Item3), max = Math.Max(x.Item2, x.Item3) })
            .Select(g => g.First());

        foreach (Tuple<string, int, int> resultItem in result)
        {
            Console.WriteLine("{0} ({1}, {2})", resultItem.Item1, resultItem.Item2, resultItem.Item3);
        }
    }

结果

object0 (1, 2)
object2 (1, 3)
object4 (2, 3)

对于字符串,您可以使用:

source
  .GroupBy(x =>
    string.Compare(x.Id0, x.Id1, false) < 0 ?
    new {min = x.Id0, max = x.Id1} :
    new {min = x.Id1, max = x.Id0})
  .Select(g => g.First());

如果您有未知数量的字符串,您可以使用 aHashSet<string>作为键和 SetComparer。

IEqualityComparer<HashSet<string>> comparer = 
  HashSet<string>.CreateSetComparer();

source
  .GroupBy(x => new HashSet<string>(x.GetStrings()), comparer)
  .Select(g => g.First());
于 2013-08-08T17:39:52.080 回答
-1

创建一个扩展方法,例如:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    var seenKeys = new HashSet<TKey>();
    return source.Where(element => seenKeys.Add(keySelector(element)));
}

然后使用它。

看看它是如何为你工作的。

于 2013-08-08T17:39:22.950 回答