使用Linq的可枚举组字段?

时间:2016-04-14 11:18:12

标签: linq

我写了这样的Linq句子:

var fs = list
    .GroupBy(i =>
        new { 
            X = i.X,
            Ps = i.Properties.Where(p => p.Key.Equals("m"))  <<<<<<<<<<<
        }
    )
    .Select(g => g.Key });

我可以按IEnumerable.Where(...)字段进行分组吗?

1 个答案:

答案 0 :(得分:0)

分组在这里不起作用。

分组时,运行时将尝试比较组密钥以生成适当的组。但是,因为在组密钥中,您使用的属性(Ps)对于IEnumerable<T>中的每个项都是不同的list(比较是在引用相等而非序列相等上)将导致每个元素的不同集合;换句话说,如果你有两个项目:

var a = new { X = 1, Properties = new[] { "m" } };
var b = new { X = 1, Properties = new[] { "m" } };

GroupBy子句将为您提供两个不同的键,如下图所示。

Grouping result

如果您的目的是将项目投影到GroupBy键的结构中,那么您不需要分组;下面的查询应该给出相同的结果:

var fs = list.Select(item => new
{
    item.X,
    Ps = item.Properties.Where(p => p.Key == "m")
});

但是,如果确实要求结果不同,则需要为结果创建单独的类,并实现与IEqualityComparer<T>子句一起使用的单独Distinct

public class Result
{
    public int X { get; set; }
    public IEnumerable<string> Ps { get; set; }
}

public class ResultComparer : IEqualityComparer<Result>
{
    public bool Equals(Result a, Result b)
    {
        return a.X == b.X && a.Ps.SequenceEqual(b.Ps);
    }

    // Implement GetHashCode
}

完成上述操作后,您可以在第一个查询中使用Distinct来获得不同的结果:

var fs = list.Select(item => new Result
{
    X = item.X,
    Ps = item.Properties.Where( p => p.Key == "m")
}).Distinct(new ResultComparer());