【问题标题】:Linq query question: Distinct based on object's propertyLinq查询问题:根据对象的属性区分
【发布时间】:2010-10-08 22:25:24
【问题描述】:

我正在将多个列表聚合到一个列表中,并希望根据 Foo (Foo.Prop1) 的一个属性使其与众不同。我无权修改 Foo 的平等比较器。

Dictionary<string, List<Foo>> fooDictionary = new Dictionary<string, List<Foo>>();
List<Foo> foovals = (from e in fooDictionary
                     where e.Key == "foo1" || e.Key == "foo2" || e.Key == "foo3"
                     select e.Value).SelectMany(f => f).ToList();

这里唯一缺少的是最后的 .Distinct(),以使 Foo 独一无二,但是,就我而言,我无法修改有关 Foo 的任何内容,因此仅调用 Distinct() 将不起作用。

有没有办法修改这个查询以返回基于 Foo.Prop1 的不同项目?

【问题讨论】:

    标签: c# linq linq-to-entities


    【解决方案1】:

    您可以将自定义相等比较器传递给Distinct()

    .SelectMany().Distinct(new FooEqualityComparer());
    

    在新文件“FooEqualityComparer.cs”中:

    public class FooEqualityComparer : IEqualityComparer<Foo>
    {
        public bool Equals(Foo x, Foo y)
        {
            return Equals(x.Prop1, y.Prop1);
        }
    
        public int GetHashCode(Foo x)
        {
            return x.Prop1.GetHashCode();
        }
    }
    

    【讨论】:

    • 另外,真的不能这样做..这是在codesmith模板中,而Foo是由xml模式动态生成的,因此甚至无法在代码模板中访问..至少我知道如何..
    • 您无需访问类代码即可编写相等比较器...
    • 我愿意,因为 Foo 是一个自定义类,相等比较器需要知道比较它们需要哪些属性
    • 那你怎么知道你想要基于它的平等呢?
    • @Sonic:我支持 codekaizen。如果乔恩的答案对你有用,那么这个也是。
    【解决方案2】:

    您可以在MoreLINQ 中使用DistinctBy 方法:

    var query = fooVals.DistinctBy(foo => foo.Property1);
    

    【讨论】:

    • 不错!不过,这是在 CodeSmith 模板中,所以不确定我是否可以添加语言扩展..
    【解决方案3】:
    var tempKeys = new HashSet<int>();    // change int to the actual type of Prop1
    
    List<Foo> foovals = (from e in fooDictionary
                         where e.Key == "foo1" || e.Key == "foo2" || e.Key == "foo3"
                         select e.Value).SelectMany(f => f)
                                        .Where(f => tempKeys.Add(f.Prop1))
                                        .ToList();
    

    【讨论】:

    • 太“聪明”且不可读。还有 hacky:Where 有副作用,哎呀。
    • @Timwi:这只是一个概念验证,几乎是 Distinct 本身在幕后所做的。将其包装在一个通用扩展方法中,该方法也接受一个键选择器函数,你刚刚重写了DistinctBy,正如 Jon 的回答中提到的那样。
    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多