L'ultimo duplicato elemento in una lista

0

Domanda

Ho un elenco contiene gli elementi duplicati.

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

Ho l'uscita postpone, access, success utilizzando

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

Avevo visto un altro esempio, si può utilizzare groupby per ottenere l'elemento più recente, poiché essi hanno un altro elemento come ID, ecc. Ora ho solo la stringa, come posso avere l'ultima voce in elenco access, postpone, success? Qualche suggerimento?

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

Migliore risposta

2

Un modo per farlo sarebbe utilizzare l'Indice dell'elemento originale collezione GroupBy. Per esempio,

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

Uscita

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

Apprezzare con il buon esempio. Aiutando tanto.
yancy
0

Il tuo ingresso in lista è solo di tipo stringa, in modo da utilizzare groupBy in realtà non aggiunge nulla. Se si considera il tuo codice, prima linea le dà l'elenco distinto, si perde solo la distinti gli elementi perché si ha una stringa.join sulla linea 2. Tutto quello che dovete fare è aggiungere una riga prima di entrare:

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

Suppongo che si potrebbe rendere il codice più conciso perché non c'è bisogno .Selezionare(a => a) né .ToArray (), nel bando di stringa.Join.

GroupBy dovrebbe essere utilizzato se si ha un elenco di classe/struttura/record/tupla elementi, in cui si potrebbe desiderare di gruppo da una chiave (o le chiavi), piuttosto che utilizzando Distinti() su tutta la faccenda. GroupBy è molto utile, si dovrebbe imparare che, e anche il ToDictionary e ToLookup LINQ la funzionalità di supporto.

2021-11-23 10:44:48
0

Un OrderedDictionary fa questo. Tutto quello che dovete fare è aggiungere i vostri articoli con una logica del "se è nel dizionario, rimuoverlo. aggiungere". OrderedDictionary conserva l'ordine di aggiungendo così la rimozione di un precedente aggiunto uno e aggiungere di nuovo, si salta alla fine del dizionario

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

Il d.Keys ora è una lista di stringhe

access
postpone
success

OrderedDictionary è in Collections.Specialized spazio dei nomi

Se si voleva che i tasti come un file CSV, è possibile utilizzare Cast per trasformarli da oggetto string

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

Grazie per l'ottima spiegazione..... Ho dovuto imparare la cosa nuova 'OrderedDictionary'.
yancy
0

Perché non si dovrebbe tornare il prima occorrenza di "rimandare"? Perché poi nella sequenza si vede la stessa parola "rimandare" di nuovo. Perché vuoi tornare prima occorrenza di "accesso"? Perché poi in sequenza non vedi questa parola in più.

Quindi: il ritorno di una parola, se il resto della sequenza non ha questa parola.

Questo sarebbe stato facile in LINQ, con la ricorsione, ma non è molto efficiente: per ogni parola è necessario controllare il resto della sequenza per vedere se la parola è in tutto il resto.

Sarebbe il modo più efficiente per ricordare il più alto indice su cui si trova una parola.

Come un metodo di estensione. Se non si ha familiarità con i metodi di estensione, vedere metodi di estensione demistificata.

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

Quindi per ogni elemento della sequenza di origine, controlliamo se è nel dizionario. Se non, si aggiunge l'elemento chiave del dizionario. Il valore è l'indice.

Se è già presente nel dizionario, quindi il valore è il più alto indice di dove abbiamo trovato questo articolo prima. A quanto pare l'attuale indice è superiore, quindi sostituiamo il valore nel dizionario.

Infine abbiamo ordine di coppie chiave-valore in il dizionario in ordine crescente di valore, e di restituire solo i tasti.

2021-11-23 21:40:54

In altre lingue

Questa pagina è in altre lingue

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