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.

Respostas:


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

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


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
}

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

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 .


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.