Как сделать Distinct для List<T>?

134
04 октября 2021, 19:10

Есть json, который я десериализовал в класс. Загружаю в cписок List. Хочу выбрать уникальные данные по параметру id. Использовал MoreLinq, yо он видит только data

public class Rootobject
{
    public Datum[] data { get; set; }
}
public class Datum
{
    public string id { get; set; }
    public string public_role_id { get; set; }
    public int oref { get; set; }
    public string[] conference_topic_ids { get; set; }
    public string conference_industry_id { get; set; }
    public DateTime? deleted_at { get; set; }
    public bool hidden { get; set; }
    public Person person { get; set; }
}
Answer 1

Можно написать свой IEqualityComparer и передавать его в параметр метода Distinct() или реализовать интерфейс IEquatable и Distinct будет сам использовать реализацию этого интерфейса для сравнения.

Создаем приватный класс внутри Datum:

        private sealed class IdEqualityComparer : IEqualityComparer<Datum>
        {
            public bool Equals(Datum x, Datum y)
            {
                if (ReferenceEquals(x, y)) return true;
                if (ReferenceEquals(x, null)) return false;
                if (ReferenceEquals(y, null)) return false;
                if (x.GetType() != y.GetType()) return false;
                return string.Equals(x.id, y.id);
                // тут можно дополнительно кастомизировать правила сравнения 
и зависимости от других полей. Например сделать case insensitive сравнение строк.
            }
            public int GetHashCode(Datum obj)
            {
                return (obj.id != null ? obj.id.GetHashCode() : 0);
            }
        }
       // наружу выставляем статическое свойство с единственным экземпляром.
        public static IEqualityComparer<Datum> IdComparer { get; } = new IdEqualityComparer();

Использование:

var uniqDatumsList = nonUniqDatumsList.Distinct(Datum.IdEqualityComparer);

с интерфейсом IEquatable чуть по-другому - его нужно просто реализовать, а Distinct уже сам его будет использовать при сравнении и передавать уже ничего не нужно. Плюс в сторону IEqualityComparer в том, что их может быть много под разные кейсы, а IEquatable будет один на все случаи и нужно учесть различные нюансы реализации GetHashCode и Equals. Поэтому IEqualityComparer тут подходит лучше.

Answer 2

Приблизительно так:

var distinctLstByProp = 
    someList
    .GroupBy (p => p.id)
    .Select  (grp => grp.FirstOrDefault())
    .ToList();

Или использовать MoreLINQ и DistinctBy() метод

var distinctLstByProp = someList.DistinctBy(p => p.id).ToList();
READ ALSO
Нужна естественная сортировка

Нужна естественная сортировка

А нужно чтобы все по порядку было

271
Можно ли получить урлы всех результатов умного фильтра в битриксе?

Можно ли получить урлы всех результатов умного фильтра в битриксе?

Пришла задача вывести в sitemapxml результаты фильтра по 2м пересечениям свойств в каталоге продукции, но я начинающий и даже пока не понимаю,...

115
Как, при определенных условиях, не вставлять значение при объявлении массива php?

Как, при определенных условиях, не вставлять значение при объявлении массива php?

Можно ли просто пропускать вставку значения в массив, когда $bool == false? Интересует пропуск вставки именно в таком виде, а не в таком:

126
Распарсить текст php

Распарсить текст php

Подскажите пожалуйста, есть такой код php

252