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

时间:2011-05-05 15:21:33

标签: c# linq entity-framework .net-4.0

我有一个对象集,想要对集合执行DISTINCT。返回的对象各有10个属性。我想使用这些属性,所以投影真的不是一个选择。在10个属性中,我只希望将DISTINCT应用于两个字段(DistrictId和ContactId)。我该怎么做?

4 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

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

MoreLINQ提供an implementation of this method

答案 2 :(得分:0)

您可以尝试构造一个匿名类型来处理这种情况。 假设您的具有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


            };

答案 3 :(得分:0)

我们可以定义一个扩展方法来对IE的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();
            }

        }

然后可以在一个简单的控制台应用程序中测试DistinctBy运算符,我们希望获得不同的(模型,颜色)元组,即我们只需要一个组合模型+颜色的汽车:

课程计划     {

    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 ...

我们没有得到物品&#34;奥迪TT Black&#34;因为我们已经有了一辆黑色奥迪。我们没有得到&#34;沃尔沃S90黑&#34;因为我们已经有了一辆黑色沃尔沃。我们买了法拉利F500,因为它们有不同的颜色。令人遗憾的是,我们被困在了Lada Limousine Rusty&#34;因为它是Model和Color的唯一组合。