Supongamos que tenemos una clase como:
class Person {
internal int PersonID;
internal string car;
}
Ahora tengo una lista de esta clase: List<Person> persons;
Ahora esta lista puede tener múltiples instancias con las mismas PersonID
, por ejemplo:
persons[0] = new Person { PersonID = 1, car = "Ferrari" };
persons[1] = new Person { PersonID = 1, car = "BMW" };
persons[2] = new Person { PersonID = 2, car = "Audi" };
¿Hay alguna forma de agruparme PersonID
y obtener la lista de todos los autos que tiene?
Por ejemplo, el resultado esperado sería
class Result {
int PersonID;
List<string> cars;
}
Entonces, después de agrupar, obtendría:
results[0].PersonID = 1;
List<string> cars = results[0].cars;
result[1].PersonID = 2;
List<string> cars = result[1].cars;
Por lo que he hecho hasta ahora:
var results = from p in persons
group p by p.PersonID into g
select new { PersonID = g.Key, // this is where I am not sure what to do
¿Podría alguien señalarme en la dirección correcta?
Count
ySum
aquí stackoverflow.com/questions/3414080/…Respuestas:
Absolutamente, básicamente quieres:
O como una expresión sin consulta:
Básicamente, el contenido del grupo (cuando se ve como un
IEnumerable<T>
) es una secuencia de los valores que estaban en la proyección (p.car
en este caso) presente para la clave dada.Para más información sobre cómo
GroupBy
funciona, vea mi publicación de Edulinq sobre el tema .(He cambiado el nombre
PersonID
aPersonId
lo anterior, para seguir las convenciones de nomenclatura de .NET ).Alternativamente, puede usar un
Lookup
:Luego puede obtener los autos para cada persona con mucha facilidad:
fuente
.GroupBy(p => new {p.Id, p.Name}, p => p, (key, g) => new { PersonId = key.Id, PersonName = key.Name, PersonCount = g.Count()})
y obtendrás a todas las personas que ocurren con una identificación, nombre y una serie de ocurrencias para cada persona.fuente
fuente
También puedes probar esto:
fuente
tratar
o
para verificar si alguna persona está repitiendo en su lista intente
fuente
He creado una muestra de código de trabajo con Query Syntax y Method Syntax. Espero que ayude a los demás :)
También puede ejecutar el código en .Net Fiddle aquí:
Aquí está el resultado:
fuente
Prueba esto :
Pero en cuanto al rendimiento, la siguiente práctica es mejor y más optimizada en el uso de la memoria (cuando nuestra matriz contiene muchos más elementos, como millones):
fuente
g.Key.PersonId
?g.SelectMany
?? Claramente no intentaste esto.SortedDictionary <PersonIdInt, SortedDictionary <CarNameString, CarInfoClass>>
. Lo más cerca que pude estar usando LINQ fueIEnumerable <IGrouping <PersonIdInt, Dictionary <CarNameString, PersonIdCarNameXrefClass>>>
. Terminé usando sufor
método de bucle que, por cierto, fue 2 veces más rápido. Además, usaría: a)foreach
vs.for
y b)TryGetValue
vs.ContainsKey
(ambos para el principio DRY - en código y tiempo de ejecución).Una forma alternativa de hacer esto podría ser seleccionar distintos
PersonId
y unirse a grupos conpersons
:O lo mismo con la sintaxis API fluida:
GroupJoin produce una lista de entradas en la primera lista (lista de
PersonId
en nuestro caso), cada una con un grupo de entradas unidas en la segunda lista (lista depersons
).fuente
El siguiente ejemplo utiliza el método GroupBy para devolver objetos agrupados por
PersonID
.O
O
O puede usar
ToLookup
, BásicamenteToLookup
usaEqualityComparer<TKey>
.Default para comparar claves y hacer lo que debe hacer manualmente cuando usa group by y to dictionary. creo que es exhumado inmemoryfuente
Primero, configure su campo clave. Luego incluya sus otros campos:
fuente