263

In C#, say I have a class called Note with three string member variables.

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

And I have a list of type Note:

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

What would be the cleanest way to get a list of all distinct values in the Author column?

I could iterate through the list and add all values that aren't duplicates to another list of strings, but this seems dirty and inefficient. I have a feeling there's some magical Linq construction that'll do this in one line, but I haven't been able to come up with anything.

0

7 Answers 7

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

This will return a sequence (IEnumerable<string>) of Author values -- one per unique value.

Sign up to request clarification or add additional context in comments.

10 Comments

Notes.Select(x => x.Author).AsParallel().Distinct(); "AsParallel()" might give some performance benefit, if we doesn't care about order and have more items in the list.
@Kiquenet, distinct considering the Default equality comparer. msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Do we need to add ToList() before .Distinct() ?
Not before the Distinct() but after, if you are trying to convert to a list. Ex: Notes.Select(x => x.Author).Distinct().ToList();
@Kirk does the IEnumerable of string still called "Author" or it has changed to anonymous? how to name a column after one has applied distinct to it? thanks
|
134

Distinct the Note class by Author

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

foreach(var item in DistinctItems)
{
    //Add to other List
}

1 Comment

Isn't it supposed to be Notes as in Notes.GroupBy() with a plural s as Note will only hold one single Note?
49

Jon Skeet has written a library called morelinq which has a DistinctBy() operator. See here for the implementation. Your code would look like

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

Update: After re-reading your question, Kirk has the correct answer if you're just looking for a distinct set of Authors.

Added sample, several fields in DistinctBy:

res = res.DistinctBy(i => i.Name).DistinctBy(i => i.ProductId).ToList();

2 Comments

Excellent, thank you. I love that it keeps the correct order if I order the list before I call the Distinct method.
I updated the links. MoreLINQ is now on Github and can be installed via Nuget: Install-Package morelinq
3
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();

By using the above logic, we can get the unique Courses.

2 Comments

your Distinct before ToList save my time.. I am doing after ToList and gives the error that cannot convert list to Ienumerable.
Distinct won't work here because for this operator every object is unique based on the hashcode of the object. You need some similar to this - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
-1

@if (dataModal.Count > 0)
{
    var DistinctItems = dataModal.GroupBy(x => x.Year).Select(y => y.First());

    <div class="col-md-3">
        <label class="fs-7 form-label text-muted">@Localizer["Year"]</label>
            <InputSelect id="ddlYears" class="form-select" @bind-Value="filter.Year">                            
                <option value="">@Localizer["Select"]</option>
                @foreach (var year in DistinctItems)
                {
                   <option value="@year.Year">
                       @year.Year
                   </option>
                }
            </InputSelect>
    </div>
}

2 Comments

How is this related to the question? Please always add an explanation, not only code.
If it's only about the second line of code, this merely repeats an existing answer, but using your own objects, which isn't really helpful.
-1

This works perfectly for me

List<string> ticketIds = new();
var uniqueTicketIds = ticketIds.Select(x => x).Distinct().ToList(); 

2 Comments

Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?
As nearly all answers here, this doesn't answer the question.
-3
mcilist = (from mci in mcilist select mci).Distinct().ToList();

2 Comments

What exactly is mci? Just an example table? The answer is a bit awkward as is.
Yeah, I don't think this does what my original question was looking for (never mind it was a year and a half ago and the project is long since finished). From what I can tell, this would work if I already had a list of Author strings which might contain duplicates, but could not be used to extract such a list from a list of objects which have the Author string as one of their fields.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.