Obtener el último duplicar elemento en una lista

0

Pregunta

Tengo una lista que contiene los elementos duplicados.

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

Obtengo el resultado que se postpone, access, success mediante el uso de

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

Yo había visto a otros de ejemplo, se puede utilizar groupby para obtener el último elemento, ya que tienen otro elemento de IDENTIFICACIÓN, etc. Ahora sólo tengo la cadena, ¿cómo puedo obtener el último elemento de la lista que es access, postpone, success? Alguna sugerencia?

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

Mejor respuesta

2

Una forma de hacerlo sería utilizar el Índice del elemento en la colección original junto con GroupBy. Por ejemplo,

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

Salida

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

Apreciar con el buen ejemplo. Ayudando mucho.
yancy
0

Su lista de entrada es sólo de tipo string, por lo que el uso de groupBy no añade nada. Si usted considera que su código, su primera línea le da la clara de la lista, sólo se pierde los distintos elementos, porque se hizo una cadena.unirse en la línea 2. Todo lo que necesita hacer es agregar una línea antes de unirse a:

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

Supongo que se podrían hacer su código más limpio debido a que no se necesita ni .Seleccione(a => a) ni .ToArray() en su llamada a la cadena.Unirse.

GroupBy podría ser utilizado si usted tenía una lista de la clase/struct/registro/tupla de elementos, donde es posible que desee para el grupo por una clave (o claves) en lugar de utilizar Distintos() en la totalidad de la cosa. GroupBy es muy útil y debe aprender de eso, y también el ToDictionary y ToLookup LINQ ayudante de funcionalidad.

2021-11-23 10:44:48
0

Un OrderedDictionary hace esto. Todo lo que tienes que hacer es agregar los elementos a ella con una lógica de "si está en el diccionario, se retire. añadir". OrderedDictionary conserva el orden de adición por la eliminación de una anterior añadió uno y volver a agregar, salta a la final del diccionario

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

Su d.Keys ahora es una lista de cadenas

access
postpone
success

OrderedDictionary es en el Collections.Specialized espacio de nombres

Si quería las llaves como un archivo CSV, puede utilizar Cast para que se conviertan de objeto a string

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

Gracias por la buena explicación..... Tuve que aprender lo nuevo 'OrderedDictionary'.
yancy
0

Así que ¿por qué no devolver la primera aparición de "posponer"? Porque más adelante en la secuencia que ver la misma palabra "posponer" de nuevo. ¿Por qué volver a la primera aparición de "acceso"? Porque más adelante en la secuencia que usted no vea esta palabra más.

Así: el retorno de una palabra si el resto de la secuencia no tiene esta palabra.

Esto sería fácil en LINQ, con la recursividad, pero no es muy eficiente: por cada palabra que tendría que revisar el resto de la secuencia para ver si la palabra está en el resto.

Sería la manera más eficiente para recordar el más alto índice en el que se encuentra una palabra.

Como un método de extensión. Si usted no está familiarizado con los métodos de extensión, consulte métodos de extensión desmitificado.

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

Así, por cada elemento de la secuencia de origen, debemos comprobar si está en el diccionario. Si no, se añade el elemento clave para el diccionario. El valor es el índice.

Si ya está en el diccionario, entonces el valor fue el más alto índice de donde hemos encontrado este artículo antes. Al parecer, el índice actual es mayor, por lo que vamos a reemplazar el valor en el diccionario.

Finalmente pedimos la clave de los pares de valores en el diccionario por orden ascendente de valor, y sólo devuelve las llaves.

2021-11-23 21:40:54

En otros idiomas

Esta página está en otros idiomas

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