2012-05-21 21 views
5

Tengo una clase Elementos con propiedades (Nombre, Precio).Eliminar elemento duplicado de la lista según la condición

Item1  $100 
    Item2  $200 
    Item3  $150 
    Item1  $500 
    Item3  $150 

Quiero eliminar elementos sólo si el nombre existe más de una vez y el precio es de $ 500 usando LINQ y sin crear comparador personalizado? para arriba, un elemento1 con $ 500 será eliminado de la lista.

Gracias,

Respuesta

8

Prueba esto:

var result = items 
    .GroupBy(item => item.Name) 
    .SelectMany(g => g.Count() > 1 ? g.Where(x => x.Price != 500) : g); 

primer grupo por su nombre. Si el grupo tiene más de 1 artículo, seleccionar los elementos del grupo en el que el precio no es 500.

+1

Esto eliminará los artículos cuyo precio sea 500 aunque no sea un duplicado. –

+0

@IgbyLargeman Tienes razón. Corregí la respuesta. –

+0

1 por estas lindas cosas. –

2

Localización de elementos duplicados se pueden hacer por:

var dups = lst.Where(x=>lst.Any(y => y != x && y.Name == x.Name)) 

Encontrar elemento duplicado con precio 500 se puede hacer por:

var dups500 = dups.Where(x=>x.Price == 500); 

Finalmente retirar dups500 se puede hacer por utilizando el método except:

var result = lst.Except(dup); 

O todo en uno:

var result = 
    lst.Except(
       lst 
       .Where(x=>x.Price == 500 && 
         lst.Any(y => y != x && y.Name == x.Name))).ToList(); 
+0

@KirkWoll, eso depende de su gusto, pero no es confuso: '' Except' significa Except', e interior 'WHERE' búsquedas de elementos con los criterios dados, parece simple pero que depende :) a tu elección (también esto es más rápido que groupby one). –

+1

Esto no mantiene ambos Item3s –

+0

@KirkWoll, solo editado. –

1
var result = from np in NamePriceCollection 
where NamePriceCollection.Count(x => x.Name == np.Name) > 1 && np.Price == 500 
select np; 

// que tenga la lista de artículos para la condición especificada aquí. Eliminarlos de la colección subyacente

4
var result = 
    from item in items 
    where item.Price != 500 || items.Count(i => i.Name == item.Name) == 1 
    select item; 
3

me gustaría crear primero un pre-evaluados lista subconjunto duplicados que contienen:

var dupes = list.Where(a => list.Count(b => b.Name.Equals(a.Name)) > 1).ToList(); 

.ToList() asegura que esta consulta solo se evalúa una vez. Esto hará que gran diferencia en la velocidad si la lista es grande.

Ahora bien, si su lista es un List<>, se puede utilizar el método de RemoveAll():

list.RemoveAll(item => item.Price == 500 && dupes.Contains(item)); 

y ya está.

Pero si su lista sólo es conocido por ser IEnumerable<>, o si no desea modificar la lista de origen, o si desea ejecución diferida, a continuación, sólo tiene que utilizar LINQ:

var result = list.Where(item => !(item.Price == 500 && dupes.Contains(item))); 

Esto se evalúa cuando usted enumera result.

0

Quiero eliminar elementos sólo si el nombre existe más de una vez y el precio es $ 500

Apple 300 <-- winner 
Apple 500 <-- dupe 
Banana 500 <-- winner 
Banana 500 <-- dupe 
Banana 500 <-- dupe 
Cantelope 100 <-- winner 
Cantelope 200 <-- winner 

La segunda manzana es una víctima, obviamente. El plátano tiene tres elementos con precio == 500. Uno es un ganador. El resto son tontos.No hay precio == 500 Cantelopes, por lo que no hay tontos, solo ganadores.

from item in source 
group item by item.Name into g 
let okItems = g.Where(x => x.Price != 500) 
let secondChoiceItem = g.FirstOrDefault(x => x.Price == 500) 
let theItems = okItems.DefaultIfEmpty(secondChoiceItem) 
from nonDupeItem in theItems 
select nonDupeItem 
-2
var Test = (from row in DataTable.AsEnumerable() 
      select row.Field<string>("ColumnName")).Distinct(); 
Cuestiones relacionadas