LINQ两个方向上的多个属性不同

时间:2013-08-08 17:30:16

标签: c# linq distinct

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

示例:

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。我是否需要自己进行比较以完成此操作?

2 个答案:

答案 0 :(得分: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());

如果你有一个未知数量的字符串,你可以使用HashSet<string>作为密钥和SetComparer。

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

source
  .GroupBy(x => new HashSet<string>(x.GetStrings()), comparer)
  .Select(g => g.First());

答案 1 :(得分:-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)));
}

然后使用它。

了解这对您有何帮助。