Obtenha uma lista de valores distintos em Lista

175

Em C #, digamos que eu tenha uma classe chamada Note com três variáveis ​​de membro String.

public class Note
{
    public string Title;
    public string Author;
    public string Text;
}

E eu tenho uma lista do tipo Nota:

List<Note> Notes = new List<Note>();

Qual seria a maneira mais limpa de obter uma lista de todos os valores distintos na coluna Autor?

Eu poderia percorrer a lista e adicionar todos os valores que não são duplicados a outra lista de strings, mas isso parece sujo e ineficiente. Sinto que há alguma construção mágica do Linq que fará isso em uma linha, mas não consegui pensar em nada.

Darrel Hoffman
fonte

Respostas:

331
Notes.Select(x => x.Author).Distinct();

Isso retornará uma sequência ( IEnumerable<string>) de Authorvalores - uma por valor exclusivo.

Kirk Woll
fonte
1
Notas.Selecione (x => x.Author) .AsParallel (). Distinct (); "AsParallel ()" pode oferecer algum benefício de desempenho, se não nos importarmos com o pedido e tivermos mais itens na lista.
Sai
1
@Kiquenet, distinto considerando o Defaultcomparador de igualdade. msdn.microsoft.com/pt-br/library/bb348436(v=vs.110).aspx
Georg Patscheider
Precisamos adicionar ToList () antes de .Distinct ()?
Phan Đức Bình
1
Não antes do Distinct (), mas depois, se você estiver tentando converter em uma lista. Ex: Notes.Select (x => x.Author) .Distinct (). ToList ();
precisa saber é o seguinte
87

Distinta a classe Note por autor

var DistinctItems = Note.GroupBy(x => x.Author).Select(y => y.First());

foreach(var item in DistinctItems)
{
    //Add to other List
}
atik sarker
fonte
1
Não deveria estar Notesno Notes.GroupBy()plural, spois Notesó conterá uma única nota?
Kkkilla
30

Jon Skeet escreveu uma biblioteca chamada morelinq, que possui um DistinctBy()operador. Veja aqui a implementação. Seu código seria semelhante

IEnumerable<Note> distinctNotes = Notes.DistinctBy(note => note.Author);

Atualização: depois de reler sua pergunta, Kirk tem a resposta correta se você está procurando apenas um conjunto distinto de autores.

Exemplo adicionado, vários campos no DistinctBy:

res = res.DistinctBy(i => i.Name).DistinctBy(i => i.ProductId).ToList();
Dan Busha
fonte
Excelente, obrigado. Eu amo que ele mantenha a ordem correta se eu pedir a lista antes de chamar o método Distinct.
Vilhelm
Eu atualizei os links. O moreLINQ agora está no Github e pode ser instalado via Nuget:Install-Package morelinq
Chad Levy
2
public class KeyNote
{
    public long KeyNoteId { get; set; }
    public long CourseId { get; set; }
    public string CourseName { get; set; }
    public string Note { get; set; }
    public DateTime CreatedDate { get; set; }
}

public List<KeyNote> KeyNotes { get; set; }
public List<RefCourse> GetCourses { get; set; }    

List<RefCourse> courses = KeyNotes.Select(x => new RefCourse { CourseId = x.CourseId, Name = x.CourseName }).Distinct().ToList();

Usando a lógica acima, podemos obter os Courses exclusivos .

Bhaskar
fonte
seu Distinct before ToList economiza meu tempo. Estou fazendo o ToList e dá o erro que não pode converter a lista em Ienumerable.
Ajay2707
O Distinct não funcionará aqui porque, para esse operador, todo objeto é único com base no código de hash do objeto. Você precisa de algo parecido com isto - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek
-2
mcilist = (from mci in mcilist select mci).Distinct().ToList();
ravinderreddy Seeelam
fonte
O que exatamente é mci? Apenas uma tabela de exemplo? A resposta é um pouco estranha como está.
Brad Koch
1
Sim, acho que isso não é o que minha pergunta original estava procurando (não importa se foi há um ano e meio atrás e o projeto já está há muito tempo concluído). Pelo que sei, isso funcionaria se eu já tivesse uma lista de cadeias de autor que podem conter duplicatas, mas não pudesse ser usada para extrair essa lista de uma lista de objetos que tenham a cadeia de autor como um de seus campos.
Darrel Hoffman