Získat poslední duplicitní prvek v seznamu

0

Otázka

Mám seznam obsahuje duplicitní položky.

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

Jsem ten výstup, který je postpone, access, success pomocí

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

Měla jsem viděla další příklad, mohou využít groupby získat poslední prvek, protože mají jiné položky, jako je ID atd. Teď mám jen string, jak se dostanu na poslední položku v seznamu, který je access, postpone, success? Nějaké návrhy?

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

Nejlepší odpověď

2

Jeden způsob, jak to udělat, by bylo použít Index položky v originální kolekci spolu s Group by. Například,

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

Výstup

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

Oceňuji, s pěkným příkladem. Moc pomáhá.
yancy
0

Vaše vstupní seznam je pouze typu string, takže si pomocí group by není opravdu nic přidávat. Pokud se domníváte, váš kód, vaše první řádek vám dává výraznou seznamu, ztratíte pouze odlišné položky, protože jste řetězec.připojte se k on-line 2. Vše, co musíte udělat, je přidat řádek předtím, než se připojíte:

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

Předpokládám, že jste mohl udělat váš kód více uhlazená, protože ti třeba ani jedno .Vyberte(a => a), ani .ToArray() ve vašem volání string.Připojit se.

Group by být použit, pokud jste měli seznam class/struct/záznam/n-tice položky, kam budete chtít seskupit podle určitého klíče (nebo klíčů), spíše než s použitím Odlišných() na celou věc. Seskupení je velmi užitečné, a měli byste se naučit, že, a také ToDictionary a ToLookup LINQ pomocné funkce.

2021-11-23 10:44:48
0

O OrderedDictionary to dělá. Vše, co musíte udělat, je přidat své položky, aby to s logikou "když to je ve slovníku, odstraňte ji. přidat". OrderedDictionary zachovává pořadí přidávání takže tím, že odstraní dřívější přidal jeden a re-adding to skočí na konec slovníku

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

Vaše d.Keys je nyní seznam řetězců

access
postpone
success

OrderedDictionary je v Collections.Specialized obor názvů

Pokud by jste chtěli klíče jako CSV, můžete použít Cast aby se obrátili od objektu na řetězec

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

Díky za dobré vysvětlení..... Musel jsem se naučit novou věc 'OrderedDictionary'.
yancy
0

Tak proč by neměla vrátí první výskyt "odložit"? Protože později v sekvenci uvidíte stejné slovo "odložit" znovu. Proč by vás vrátí první výskyt "přístup"? Protože později v pořadí nevidíte toto slovo už.

Takže: vrátit slovo, pokud zbytek sekvence nemá toto slovo.

To by bylo snadné v LINQ, s rekurze, ale to není moc účinné: pro každé slovo, které budete muset zkontrolovat, zbytek sekvence, zda slovo je v klidu.

To by bylo mnohem efektivnější, aby vzpomenout na nejvyšší index, na kterém jste našli slovo.

Jako způsob rozšíření. Pokud nejste obeznámeni s příponou metody, viz rozšíření metody mýtů zbavená.

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

Takže pro každou položku ve zdrojovém sekvence, můžeme zkontrolovat, pokud to je ve slovníku. Pokud ne, musíme přidat položky jako klíč slovníku. Hodnota je index.

Pokud je již ve slovníku, pak je hodnota nejvyššího indexu, kde jsme našli tento produkt předtím. Zdá se, že současný index je vyšší, takže jsme nahradit hodnotu ve slovníku.

Nakonec jsme se objednat dvojice klíč-hodnota ve slovníku vzestupně podle hodnoty, a vrátit se pouze klíče.

2021-11-23 21:40:54

V jiných jazycích

Tato stránka je v jiných jazycích

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