Vamos supor que se tivermos uma classe como:
class Person {
internal int PersonID;
internal string car;
}
Agora eu tenho uma lista desta classe: List<Person> persons;
Agora, esta lista pode ter várias instâncias com as mesmas PersonID
, por exemplo:
persons[0] = new Person { PersonID = 1, car = "Ferrari" };
persons[1] = new Person { PersonID = 1, car = "BMW" };
persons[2] = new Person { PersonID = 2, car = "Audi" };
Existe uma maneira de agrupar PersonID
e obter a lista de todos os carros que ele tem?
Por exemplo, o resultado esperado seria
class Result {
int PersonID;
List<string> cars;
}
Então, após o agrupamento, eu obteria:
results[0].PersonID = 1;
List<string> cars = results[0].cars;
result[1].PersonID = 2;
List<string> cars = result[1].cars;
Pelo que fiz até agora:
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
Alguém pode por favor me dizer a direção correta?
Count
eSum
aqui stackoverflow.com/questions/3414080/…Respostas:
Absolutamente - você basicamente quer:
Ou como uma expressão sem consulta:
Basicamente, o conteúdo do grupo (quando visto como um
IEnumerable<T>
) é uma sequência de quaisquer valores presentes na projeção (p.car
neste caso) presentes para a chave especificada.Para saber mais sobre como
GroupBy
funciona, consulte minha publicação do Edulinq sobre o assunto .(Eu tenho renomeado
PersonID
paraPersonId
no exemplo acima, a seguir NET convenções de nomenclatura .)Como alternativa, você pode usar um
Lookup
:Você pode obter os carros para cada pessoa com muita facilidade:
fonte
.GroupBy(p => new {p.Id, p.Name}, p => p, (key, g) => new { PersonId = key.Id, PersonName = key.Name, PersonCount = g.Count()})
e obterá todas as pessoas que ocorrem com um ID, nome e várias ocorrências para cada pessoa.fonte
fonte
Você também pode tentar isso:
fonte
tentar
ou
para verificar se alguém está repetindo na sua lista, tente
fonte
Eu criei um exemplo de código de trabalho com sintaxe de consulta e sintaxe de método. Espero que ajude os outros :)
Você também pode executar o código no .Net Fiddle aqui:
Aqui está o resultado:
fonte
Tente o seguinte:
Mas em termos de desempenho, a prática a seguir é melhor e mais otimizada no uso de memória (quando nossa matriz contém muito mais itens como milhões):
fonte
g.Key.PersonId
?g.SelectMany
?? Você claramente não tentou isso.SortedDictionary <PersonIdInt, SortedDictionary <CarNameString, CarInfoClass>>
. O mais próximo que pude usar o LINQ foiIEnumerable <IGrouping <PersonIdInt, Dictionary <CarNameString, PersonIdCarNameXrefClass>>>
. Acabei usando ofor
método loop, que, btw, era 2x mais rápido. Além disso, eu usaria: a)foreach
vs.for
eb)TryGetValue
vs.ContainsKey
(ambos pelo princípio DRY - em código e tempo de execução).Uma maneira alternativa de fazer isso pode ser selecionar distintos
PersonId
e ingressar no grupopersons
:Ou o mesmo com a sintaxe fluente da API:
GroupJoin produz uma lista de entradas na primeira lista (lista de
PersonId
no nosso caso), cada uma com um grupo de entradas unidas na segunda lista (lista depersons
).fonte
O exemplo a seguir usa o método GroupBy para retornar objetos agrupados por
PersonID
.Ou
Ou
Ou você pode usar
ToLookup
, BasicamenteToLookup
usaEqualityComparer<TKey>
.Default para comparar chaves e fazer o que você deve fazer manualmente ao usar agrupar por e para dicionário. eu acho que é excutado em memóriafonte
Primeiro, defina seu campo-chave. Em seguida, inclua seus outros campos:
fonte