Как выполнить запрос DISTINCT с помощью LINQ (.NET 4)? - PullRequest
2 голосов
/ 05 мая 2011

У меня есть набор объектов, и я хочу выполнить DISTINCT для коллекции.Возвращенные объекты имеют около 10 свойств каждый.Я хочу использовать свойства, так что проецирование действительно не вариант.Из 10 свойств я хочу, чтобы DISTINCT применялся только к двум полям (DistrictId и ContactId).Как мне это сделать?

Ответы [ 4 ]

4 голосов
/ 05 мая 2011

Поскольку вам нужны только элементы, которые отличаются с точки зрения комбинации DistrictId и ContactId, вы можете использовать GroupBy, а затем решите, как вы хотите обрабатывать дубликаты.Каждая группа в этом случае представляет элементы, которые попадают в одну отдельную комбинацию.

var results = context.MyCollection
                     .GroupBy( x=> new { x.DistrictId, x.ContactId })
                     .Select(...)
1 голос
/ 05 мая 2011

Вам необходимо написать свой собственный или получить реализацию метода DistinctBy, который позволяет различать проецируемую информацию о содержании последовательности, сохраняя при этом тип последовательности.

MoreLINQ обеспечивает реализацию этого метода .

0 голосов
/ 02 октября 2015

Мы можем определить метод расширения для выполнения операции DistinctBy для IEnumerable с T, как показано ниже:

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

Мы не получили предмет «Audi TT Black», потому что у нас уже есть черная Audi.Мы не получили "Volvo S90 Black", потому что мы уже получили черный Volvo.Мы получили оба Ferrari F500, потому что они получили разные цвета.И, к сожалению, мы застряли с «Lada Limousine Rusty», так как это была единственная комбинация модели и цвета.

0 голосов
/ 05 мая 2011

Вы можете попробовать создать анонимный тип для обработки этого случая. Предположим, ваш класс с 10 свойствами - Элемент

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


            };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...