Получить последний дубликат элемента в списке

0

Вопрос

У меня есть список, содержащий дубликаты элементов.

List<string> filterList = new List<string>()
{
     "postpone", "access", "success", "postpone", "success"
};

Я получаю результат, который является postpone, access, success с помощью

List<string> filter = filterList.Distinct().ToList();
string a = string.Join(",", filter.Select(a => a).ToArray());
Console.WriteLine(a);

Я видел другой пример, они могут использовать groupby чтобы получить последний элемент, так как у них есть другой элемент, такой как идентификатор и т. Д. Теперь у меня есть только строка, как я могу получить последний элемент в списке, который access, postpone, success? Есть какие-нибудь предложения?

c# linq
2021-11-23 10:34:46
4

Лучший ответ

2

Одним из способов сделать это было бы использовать индекс элемента в исходной коллекции вместе с GroupBy. Например,

    var lastDistinct = filterList.Select((x,index)=> new {Value=x,Index=index})
                                 .GroupBy(x=>x.Value)
                                 .Select(x=> x.Last())
                                 .OrderBy(x=>x.Index)
                                 .Select(x=>x.Value);
    var result = string.Join(",",lastDistinct);

Выход

access,postpone,success
2021-11-23 10:58:27

Оцените с хорошим примером. Так сильно помогаю.
yancy
0

Ваш список ввода имеет только строковый тип, поэтому использование groupBy на самом деле ничего не добавляет. Если вы рассмотрите свой код, ваша первая строка даст вам отдельный список, вы потеряете отдельные элементы только потому, что сделали строку.присоединяйтесь к строке 2. Все, что вам нужно сделать, это добавить строку, прежде чем присоединиться:

List<string> filter = filterList.Distinct().ToList();
string last = filter.LastOrDefault();
string a = string.Join(",", filter.Select(a => a).ToArray());
Console.WriteLine(a);

Я полагаю, вы могли бы сделать свой код более кратким, потому что вам не нужно ни то, ни другое .Выберите(a => a) ни .toArray() в вашем вызове string.Join.

GroupBy будет использоваться, если у вас есть список элементов класса/структуры/записи/кортежа, где вы можете захотеть сгруппироваться по определенному ключу (или ключам), а не использовать Distinct() во всем. GroupBy очень полезен, и вам следует изучить это, а также вспомогательные функции ToDictionary и ToLookup LINQ.

2021-11-23 10:44:48
0

Это делает упорядоченный каталог. Все, что вам нужно сделать, это добавить в него свои элементы с логикой "если это есть в словаре, удалите его. добавьте это". OrderedDictionary сохраняет порядок добавления, поэтому, удалив ранее добавленный и повторно добавив его, он переходит в конец словаря

var d = new OrderedDictionary();
filterList.ForEach(x => { if(d.Contains(x)) d.Remove(x); d[x] = null; });

Ваш d.Keys теперь это список строк

access
postpone
success

Упорядоченный каталог находится в Collections.Specialized пространство имен

Если вам нужны ключи в формате CSV, вы можете использовать Cast чтобы превратить их из объекта в строку

var s = string.Join(",", d.Keys.Cast<string>());
2021-11-23 18:59:40

Спасибо за хорошее объяснение..... Я выучил новую вещь "Упорядоченный запрет".
yancy
0

Так почему бы вам не вернуть первое появление "отложить"? Потому что позже в этой последовательности вы снова увидите то же самое слово "отложить". Зачем вам возвращать первое вхождение "доступа"? Потому что позже в последовательности вы больше не видите это слово.

Итак: верните слово, если в остальной части последовательности этого слова нет.

Это было бы легко в LINQ с рекурсией, но это не очень эффективно: для каждого слова вам придется проверять остальную часть последовательности, чтобы увидеть, есть ли слово в остальных.

Было бы гораздо эффективнее запомнить самый высокий индекс, по которому вы нашли слово.

В качестве метода расширения. Если вы не знакомы с методами расширения, см. раздел Методы расширения, разглашенные.

private static IEnumerable<T> FindLastOccurences<T>(this IEnumerable<T> source)
{
    return FindLastOccurrences<T>(source, null);
}

private static IEnumerable<T> FindLastOccurences<T>(this IEnumerable<T> source,
    IEqualityComparer<T> comparer)
{
    // TODO: check source not null
    if (comparer == null) comparer = EqualityComparer<T>.Default;

    Dictionary<T, int> dictionary = new Dictionary<T, int>(comparer);

    int index = 0;
    foreach (T item in source)
    {
        // did we already see this T? = is this in the dictionary
        if (dictionary.TryGetValue(item, out int highestIndex))
        {
            // we already saw it at index highestIndex.
            dictionary[item] = index;
        }
        else
        {
            // it is not in the dictionary, we never saw this item.
            dictionary.Add(item, index);
        }
        ++index;
    }

    // return the keys after sorting by value (which contains the highest index)
    return dictionay.OrderBy(keyValuePair => keyValuePair.Value)
                    .Select(keyValuePair => keyValuePair.Key);
}
         

Поэтому для каждого элемента в исходной последовательности мы проверяем, есть ли он в словаре. Если нет, мы добавим элемент в качестве ключа в словарь. Значение - это индекс.

Если он уже есть в словаре, то значение было самым высоким показателем того, где мы находили этот элемент раньше. Очевидно, текущий индекс выше, поэтому мы заменяем значение в словаре.

Наконец, мы упорядочиваем пары значений ключей в словаре по возрастанию и возвращаем только ключи.

2021-11-23 21:40:54

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................