Zobacz ostatni duplikat elementu na liście

0

Pytanie

Mam listę, która zawiera duplikaty elementów.

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

Dostaję wynik, który jest postpone, access, success z pomocą

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

Widziałem inny przykład, mogą one korzystać groupby aby uzyskać ostatni element, tak jak u nich jest inny element, taki jak identyfikator itp. Teraz mam tylko wiersz, jak mogę dostać ostatni element w liście, który access, postpone, success? Jakieś sugestie?

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

Najlepsza odpowiedź

2

Jednym ze sposobów, aby to zrobić byłoby użyć indeks elementu w oryginalnej kolekcji wraz z GroupBy. Na przykład,

    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);

Wyjście

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

Ocenić z tego dobrym przykładem. Tak bardzo pomagam.
yancy
0

Twoja lista wejścia ma tylko typu string, więc korzystanie z groupBy właściwie nic nie dodaje. Jeśli wziąć pod uwagę swój kod, twoja pierwsza linia daje osobna lista, stracisz poszczególne elementy tylko dlatego, że zrobili wiersz.dołącz do linii 2. Wszystko, co musisz zrobić, to dodać wiersz, zanim dołączyć:

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

Przypuszczam, że można by zrobić swój kod jest bardziej zwięzły, bo nie trzeba ani jedno, ani drugie .Wybierz(a => a) brak .toArray() w swoim wywołaniu string.Join.

GroupBy będzie używany, jeśli masz listę elementów klasy/struktury/nagrywania/tkę, gdzie można chcieć być zgrupowane według określonego klucza (lub kluczy), a nie korzystać z Distinct() we wszystkim. GroupBy bardzo przydatny, i należy to zbadać, a także funkcje pomocnicze ToDictionary i ToLookup LINQ.

2021-11-23 10:44:48
0

To sprawia, że uporządkowany katalog. Wszystko, co musisz zrobić, to dodać do niego własne elementy z logiką "jeśli to jest w słowniku, należy go usunąć. dodaj to". OrderedDictionary zachowuje kolejność dodania, więc usuwając wcześniej dodany i ponowne dodanie go, on przechodzi na koniec słownika

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

Twój d.Keys teraz to jest lista wierszy

access
postpone
success

Uporządkowany katalog znajduje się w Collections.Specialized przestrzeń nazw

Jeśli potrzebujesz klucze w formacie CSV, można użyć Cast aby włączyć je z obiektu w ciąg

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

Dziękuję za dobre wyjaśnienie..... Nauczyłem się nowej rzeczy "Uporządkowana bana".
yancy
0

Więc dlaczego nie można odzyskać pierwsze pojawienie się "odłożyć"? Bo później w tej sekwencji można ponownie zobaczyć to samo słowo "odłożyć". Po co zwracać pierwsze wystąpienie "dostępu"? Bo później w kolejności już nie patrz na to słowo.

Tak więc: oddajcie słowo, jeśli w pozostałej części sekwencji tego słowa nie ma.

To byłoby łatwe w LINQ z rekursji, ale nie jest to bardzo skutecznie: dla każdego słowa trzeba sprawdzać resztę sekwencji, aby zobaczyć, czy są jakieś słowo w pozostałych.

Byłoby znacznie lepiej zapamiętać najwyższy wskaźnik, według którego znalazłeś słowo.

Jako metodę rozszerzenia. Jeśli nie jesteś zaznajomiony z metodami dany, patrz Metody rozszerzenia, ujawnionych.

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);
}
         

Dlatego dla każdego elementu w oryginalnej kolejności sprawdzamy, czy jest on w słowniku. Jeśli nie, możemy dodać element jako klucz w słowniku. Wartość - jest to wskaźnik.

Jeśli już istnieje w słowniku znaczenie było najwyższym wskaźnikiem tego, gdzie znajdowaliśmy ten element wcześniej. Oczywiście, aktualny indeks wyżej, więc zamieniamy wartość w słowniku.

W końcu, my porządkujemy pary wartości kluczy w słowniku rosnąco i zwracamy tylko klucze.

2021-11-23 21:40:54

W innych językach

Ta strona jest w innych językach

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