У меня есть объект с именем "response" типа <LabelResponse>, который содержит объект с именем "items" типа IEnumerable<PostLabelResponse>. Этот PostLabelResponse содержит 2 строки с именами "Key" и "Category". IEnumerable содержит повторяющиеся значения этого PostLabelResponse. Как я могу удалить эти дубликаты по значению "Key" и вернуть "response"?

Я пробовал с response.items.Distinct() из LinQ, но это не сработало

0
LOU DAMN 2 Фев 2022 в 22:16
2
Кажется, вы должны объяснить .net, какие экземпляры PostLabelResponse равны. Вы можете либо реализовать методы Equals и GetHashCode в PostLabelResponse, либо написать и использовать компаратор, класс, реализующий интерфейс IEqualityComparer<PostLabelResponse>.
 – 
Dmitry Bychenko
2 Фев 2022 в 22:24
Поэтому у меня есть это: ответ: [ {ключ: «Малый», значение: «Стандартный»}, {ключ: «Малый», значение: «Стандартный»}, {ключ: «Средний», значение: «Стандартный»}, {ключ: «Большой», значение: «Стандартный»}, {ключ: «Громоздкий», значение: «Громоздкий»}, {ключ: «Громоздкий», значение: «Громоздкий»}]
 – 
LOU DAMN
2 Фев 2022 в 22:35
1
Этот код (пожалуйста, поместите код при редактировании вопроса, а не как неформатированный текст в комментарии) не содержит атрибута/свойства, называемого «элементы».
 – 
Caius Jard
2 Фев 2022 в 22:50

2 ответа

Кажется, что ваш текущий PostLabelResponse, который, как я предполагаю, выглядит примерно так

public class PostLabelResponse {
  ...

  public string Key {get; set;}
  public string Value {get; set;}

  ...
}

Не предоставляет настраиваемый метод Equals и GetHashCode и вот почему .Net использует по умолчанию (которые сравнивают ссылки, а не значения). Если вы хотите сравнить значения, скажем, Key, а не Value, вы можете реализовать Equals и GetHashCode:

    public class PostLabelResponse {
      public string Key { get; set; }
      public string Value { get; set; }

      ...

      public override bool Equals(object obj) {
        if (ReferenceEquals(this, obj))
          return true;

        return obj is PostLabelResponse other &&
          Key == other.Key;
      }

      public override int GetHashCode() =>
        Key?.GetHashCode() ?? 0;
    }

С этого момента Distinct() начинает использовать ваши правила (Equals и GetHashCode). Или вы можете реализовать пользовательский компаратор:

    public sealed class MyComparer : IEqualityComparer<PostLabelResponse> {
      public bool Equals(PostLabelResponse x, PostLabelResponse y) {
        if (ReferenceEquals(x, y))
          return true;
        if (null == x || null == y)
          return false;

        return (x.Key == y.Key);
      }

      public int GetHashCode(PostLabelResponse obj) {
        return obj?.Key?.GetHashCode() ?? 0;
      }
    }

Который вы должны указать при использовании Distinct:

    .Distinct(new MyComparer())
1
Dmitry Bychenko 3 Фев 2022 в 11:15
Вопрос довольно неясен, но я интерпретировал его только по ключу --> Как я могу удалить эти дубликаты по значению «Ключ»
 – 
Caius Jard
2 Фев 2022 в 23:03
Да, извините за мой английский
 – 
LOU DAMN
3 Фев 2022 в 10:15
DAMN: я изменил ответ, теперь сравниваются только Key
 – 
Dmitry Bychenko
3 Фев 2022 в 11:18

.NET 6 представила DistinctBy. метод, который можно использовать для поиска дубликатов на основе определенных свойств, а не всего объекта. В предыдущих версиях тот же метод был доступен в MoreLINQ. библиотека. Вы можете добавить пакет NuGet, но оператор настолько мал, что вы можете легко добавить его в свой проект в качестве исходного кода.

Предполагая, что ваш класс:

public class PostLabelResponse {
  ...

  public string Key {get; set;}
  public string Value {get; set;}

  ...
}

Вы можете получить отдельные объекты с помощью:

var distinct=response.items.DistinctBy(x=>x.Key);

Код оператора очень короткий:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, 
    IEqualityComparer<TKey>? comparer=null)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));

    return _(); IEnumerable<TSource> _()
    {
        var knownKeys = new HashSet<TKey>(comparer);
        foreach (var element in source)
        {
            if (knownKeys.Add(keySelector(element)))
                yield return element;
        }
    }
}
0
Panagiotis Kanavos 3 Фев 2022 в 11:25