繁体   English   中英

如何使用LINQ(.NET 4)执行DISTINCT查询?

[英]How do I perform a DISTINCT query using LINQ (.NET 4)?

我有一个对象集,想对集合执行DISTINCT。 返回的对象每个都有大约10个属性。 我想使用这些属性,因此投影确实不是一种选择。 在这10个属性中,我只想将DISTINCT应用于两个字段(DistrictId和ContactId)。 我该怎么做呢?

由于只需要在DistrictId和ContactId组合方面不同的元素,因此可以使用GroupBy ,然后决定要如何处理重复项。 在这种情况下,每个组代表属于一个不同组合的项目。

var results = context.MyCollection
                     .GroupBy( x=> new { x.DistrictId, x.ContactId })
                     .Select(...)

您需要编写自己的代码或获得DistinctBy方法的实现,该方法允许您在保留序列类型的同时对序列内容的投影信息进行区分。

MoreLINQ提供了此方法的实现

我们可以定义一个扩展方法来对T的IEnumerable进行DistinctBy操作,如下所示:

public static class EnumerableExtensions
        {

            /// <summary>
            /// Returns a ienumerable which is distinct by a given property key selector. If a custom equality 
            /// comparer is to be used, pass this in as the comparer. By setting the comparer default to null,
            /// the default comparer is used. 
            /// </summary>
            /// <typeparam name="T">The item type in the ienumerable</typeparam>
            /// <typeparam name="TKey">The type of the key selector (property to disinct elements by)</typeparam>
            /// <param name="coll">The source ienumerable</param>
            /// <param name="keySelector">The key selector, use a member expression in a lambda expression</param>
            /// <param name="comparer">Custom comparer to use, pass in null here to specify that default comparer is used,
            /// however, this is default set to null and not required parameter</param>
            /// <returns></returns>
            public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> coll, Func<T, TKey> keySelector,
                IEqualityComparer<TKey> comparer = null)
            {
                if (coll == null)
                    throw new ArgumentNullException("coll");
                if (keySelector == null)
                    throw new ArgumentNullException("keySelector");

                var result = coll.GroupBy(keySelector, comparer).Select(g => g.First()).ToList();
                return new List<T>(result).AsEnumerable();
            }

        }

然后可以在一个简单的Console应用程序中测试DistinctBy运算符,在该应用程序中我们想要获取不同的(模型,颜色)元组,即我们只需要Model + Color组合中的一辆汽车:

课程计划{

    static void Main(string[] args)
    {

        var cars = new []
        {
            new Car {Model = "Audi", Make = "A4", Color = "Black"},
            new Car {Model = "Audi", Make = "A8", Color = "Red"},
            new Car {Model = "Audi", Make = "TT", Color = "Black"},
            new Car {Model = "Volvo", Make = "XC90", Color = "Black"},
            new Car {Model = "Volvo", Make = "S90", Color = "Black"},
            new Car {Model = "Ferrari", Make = "F500", Color = "Yellow"},
            new Car {Model = "Ferrari", Make = "F500", Color = "Red"},
            new Car {Model = "Lada", Make = "Limousine", Color = "Rusty"}
        };

        var groupedCars = cars.DistinctBy(c => new {c.Model, c.Color});


        foreach (var gc in groupedCars)
        {
            Console.WriteLine(gc.ToString()); 
        }

        Console.WriteLine("Press any key to continue ...");
        Console.ReadKey(); 
    }




    // Define other methods and classes here

}

输出为:

Model: Audi, Make: A4, Color: Black
Model: Audi, Make: A8, Color: Red
Model: Volvo, Make: XC90, Color: Black
Model: Ferrari, Make: F500, Color: Yellow
Model: Ferrari, Make: F500, Color: Red
Model: Lada, Make: Limousine, Color: Rusty
Press any key to continue ...

我们没有得到“ Audi TT Black”,因为我们已经有一个黑色的奥迪。 我们没有得到“沃尔沃S90黑色”,因为我们已经有了黑色沃尔沃。 我们都得到了法拉利F500,因为它们有不同的颜色。 遗憾的是,由于“ Lada Limousine Rusty”是模型和颜色的唯一组合,因此我们陷入了困境。

您可以尝试构造匿名类型来处理这种情况。 假设您的具有10个属性的类是Element

public class Element
    {
        public int FirstProp { get; set; }
        public int SecondProp { get; set; }

       //others 8 cool properties
    }

使用linq中的扩展方法提取所需内容的查询:

IList<Element> element = new List<Element>();


            var result = new { P1 = element
                                .Select(X => X.FirstProp).Distinct()
                            ,
                               P2 = element
                                    .Select(X => X.SecondProp).Distinct()
                            ,
                                element
                               // do projections here over others 8 properties


            };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM