Самый быстрый способ удалить повторяющееся значение из списка‹› с помощью лямбда

какой самый быстрый способ удалить повторяющиеся значения из списка. Предположим, List<long> longs = new List<long> { 1, 2, 3, 4, 3, 2, 5 }; Так что мне интересно использовать лямбду для удаления дубликатов и возврата: {1, 2, 3, 4, 5}. Каково ваше предложение?


person Saeid    schedule 17.05.2012    source источник
comment
как насчет longs.Distinct()?   -  person zerkms    schedule 17.05.2012


Ответы (6)


Самый простой способ получить новый список:

List<long> unique = longs.Distinct().ToList();

Вам этого достаточно, или вам нужно изменить существующий список? Последний значительно более многословен.

Обратите внимание, что Distinct() не гарантировано чтобы сохранить первоначальный порядок, но в текущей реализации так и будет — и это самая естественная реализация. См. мою запись в блоге Edulinq о Distinct() для Дополнительная информация.

Если вам не нужно, чтобы это было List<long>, вы можете просто сохранить его как:

IEnumerable<long> unique = longs.Distinct();

На этом этапе он будет проходить дедупликацию каждый раз, когда вы перебираете unique. Хорошо это или нет, зависит от ваших требований.

person Jon Skeet    schedule 17.05.2012
comment
Спасибо, так что я думаю, что longs = longs.Distinct().ToList() правильно. Правильно? - person Saeid; 17.05.2012
comment
@Saeid: Пока ничто другое не имеет ссылки на исходный список, все должно быть в порядке. Вам нужно различать изменение самого списка и изменение переменной для ссылки на новый список (что и будет делать этот код). - person Jon Skeet; 17.05.2012
comment
Если важно изменить тот же список, не могли бы мы просто сказать: var newTmpList = longs.Distinct().ToList(); longs.Clear(); longs.AddRange(newTmpList); - person Jeppe Stig Nielsen; 18.05.2012
comment
@JeppeStigNielsen: Да, это возможно, но это не очень хороший способ сделать это... - person Jon Skeet; 18.05.2012
comment
Это сработало для меня. Мой случай, мне нужно было обновить список, поэтому я просто сделал следующее: long = long.Distinct().ToList(); - person Tscott; 19.01.2018

Вы можете использовать этот метод расширения для перечислений, содержащих более сложные типы:

IEnumerable<Foo> distinctList = sourceList.DistinctBy(x => x.FooName);

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector)
{
    var knownKeys = new HashSet<TKey>();
    return source.Where(element => knownKeys.Add(keySelector(element)));
}
person Jon Rea    schedule 05.11.2012
comment
+1 Отличный ответ - всеобъемлющие ответы всегда мне нравятся! Это именно то, что я искал. Мне нравится, что всегда существует это несоответствие между примитивными и сложными типами. Это почти так же плохо, как учить новый язык и иметь только #(*%$()*@ бесполезный пример привет, мир! Ладно, снимаю с мыльницы, отличный ответ! - person dyslexicanaboko; 30.11.2012
comment
Я также предпочитаю это решение, потому что оно использует лямбду в качестве OP, запрошенного в заголовке (примечание: Distinct() в Linq этого не делает), поэтому его можно легко использовать с другими типами данных без необходимости реализовывать Equals/GetHashCode или IEqualityComparer - person ZoolWay; 17.10.2016
comment
Очень элегантное решение, но после? У нас есть исходный список и отдельный список. Как мы можем обновить dbSet, чтобы отразить изменения в базе данных? - person Nolmë Informatique; 22.04.2017
comment
фантастический ответ! и вы хотите различать по многим ключам, просто вызывайте его несколько раз с разными селекторами клавиш :) - person Al-Hanash Moataz; 13.09.2020

Есть метод Distinct(). это должно работать.

List<long> longs = new List<long> { 1, 2, 3, 4, 3, 2, 5 };
var distinctList = longs.Distinct().ToList();
person Pongsathon.keng    schedule 17.05.2012

Если вы хотите придерживаться исходного списка вместо создания нового, вы можете сделать что-то похожее на то, что метод расширения Distinct() делает внутри, то есть использовать HashSet для проверки уникальности:

HashSet<long> set = new HashSet<long>(longs.Count);
longs.RemoveAll(x => !set.Add(x));

Класс List предоставляет удобный метод RemoveAll(predicate), который отбрасывает все элементы, не удовлетворяющие условию, заданному предикатом. Предикат — это делегат, принимающий параметр типа элемента списка и возвращающий логическое значение. Метод Add() HashSet возвращает значение true, только если набор еще не содержит элемент. Таким образом, удаляя из списка любые элементы, которые нельзя добавить в набор, вы эффективно удаляете все дубликаты.

person Wormbo    schedule 27.05.2012

Простая интуитивно понятная реализация

public static List<PointF> RemoveDuplicates(List<PointF> listPoints)
{
    List<PointF> result = new List<PointF>();

    for (int i = 0; i < listPoints.Count; i++)
    {
        if (!result.Contains(listPoints[i]))
            result.Add(listPoints[i]);
    }

    return result;
}
person Moctar Haiz    schedule 19.04.2018

На месте:

    public static void DistinctValues<T>(List<T> list)
    {
        list.Sort();

        int src = 0;
        int dst = 0;
        while (src < list.Count)
        {
            var val = list[src];
            list[dst] = val;

            ++dst;
            while (++src < list.Count && list[src].Equals(val)) ;
        }
        if (dst < list.Count)
        {
            list.RemoveRange(dst, list.Count - dst);
        }
    }
person Const Mi    schedule 28.11.2016