HOWTO · Csharp

C#에서 하나 이상의 속성을 기반으로 고유한 목록 얻기

이 문서에서는 LINQ에서 Distinct() 함수를 사용하고 C#에서 하나 이상의 속성을 기반으로 고유한 목록을 얻는 기본 사항에 대해 설명합니다.

이 페이지의 내용

오늘 우리는 다른 값을 포함하는 동일한 속성을 가진 여러 개체에 대해 LINQ에서 Distinct()를 사용하는 방법을 살펴보겠습니다. 먼저 아래 예를 살펴보십시오.

CAR one, CAR twoCAR three의 세 개체가 있다고 가정합니다. CAR oneCAR two에는 빌드 값 2가 포함되지만 CAR three에는 빌드 값 4가 포함됩니다.

세 개체에서 Distinct()를 호출할 때 결과에는 CAR oneCAR three 또는 CAR twoCAR three만 포함되어야 합니다. 둘 다 고유한 값을 포함하기 때문입니다.

이 문서에서는 C#에서 하나 이상의 속성을 기반으로 고유한 목록을 얻는 방법에 대해 설명합니다.

GroupBy()Select()를 사용하여 C#의 한 속성을 기반으로 고유한 목록 얻기

따라서 예제를 시작하기 전에 먼저 코드에 LINQ 라이브러리를 추가해 보겠습니다.

using SYSTEM.Linq;

그런 다음 다음과 같이 CAR 클래스를 정의해 보겠습니다.

class CAR {
  public int id;

  public CAR(int id) {
    this.id = id;
  }
}

그런 다음 Main에서 몇 가지 개체를 정의해 보겠습니다.

CAR one = new CAR(4);
CAR two = new CAR(4);
CAR three = new CAR(6);

List<CAR> cars = new List<CAR>();
cars.Add(one);
cars.Add(two);
cars.Add(three);

또한 목록을 만들고 여기에 세 개의 개체를 추가했습니다. 동일한 속성 개체를 트리밍하고 그중 하나만 고려합니다.

새 목록을 만든 다음 GroupBY() 절을 사용합니다. 그리고 마지막으로 우승자를 뽑는 First().

List<CAR> distinct_c = cars.GroupBy(p => p.id).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

결과는 다음과 같이 나옵니다.

4 6

이들은 세 개체 각각에 있는 두 개의 고유한 ID였습니다. 전체 코드는 다음과 같습니다.

class pointer {
  class CAR {
    public int id;

    public CAR(int id) {
      this.id = id;
    }
  }

  public static void Main(String[] args) {
    CAR one = new CAR(4);
    CAR two = new CAR(4);
    CAR three = new CAR(6);

    List<CAR> cars = new List<CAR>();
    cars.Add(one);
    cars.Add(two);
    cars.Add(three);

    List<CAR> distinct_c = cars.GroupBy(p => p.id).Select(g => g.First()).ToList();
    for (int i = 0; i < distinct_c.Count(); i++) {
      Console.Write(distinct_c[i].id + " ");
    }
  }
}

위의 코드를 네임스페이스에 삽입한 다음 사용하십시오.

GroupBy()Select()를 사용하여 C#의 하나 이상의 속성을 기반으로 고유한 목록 얻기

id와 함께 color라는 속성이 하나 더 있고 여전히 고유한 속성을 선택하고 싶다면 어떻게 해야 할까요? 다음과 같이 CAR 클래스에 color 속성을 추가해 보겠습니다.

class CAR {
  public int id;
  public string color;

  public CAR(int id, string color) {
    this.id = id;
    this.color = color;
  }
}

그러나 이제 위와 동일한 구문을 사용하여 함수를 호출해야 합니다.

CAR one = new CAR(4, "red");
CAR two = new CAR(4, "blue");
CAR three = new CAR(6, "blue");

List<CAR> cars = new List<CAR>();
cars.Add(one);
cars.Add(two);
cars.Add(three);

List<CAR> distinct_c = cars.GroupBy(p => p.id).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

출력은 4 6과 동일하게 유지됩니다. p는 여전히 p => p.id에 의해서만 그룹화되기 때문입니다. 그러나 이제 색상으로도 구분하기를 원하므로 다음과 같이 할 수 있습니다.

List<CAR> distinct_c = cars.GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

결과는 어떻게 될까요? 세 개체는 IDCAR의 조합이 모두 다르기 때문입니다. (4, 빨간색), (4, 파란색)(6, 파란색). 그러므로 모든 대상 사이에는 구별이 있다.

이제 출력은 다음과 같습니다.

4 4 6

전체 코드는 다음과 같습니다.

using System;
using System.Collections.Generic;
using System.Linq;

static class pointer {
  class CAR {
    public int id;
    public string color;

    public CAR(int id, string color) {
      this.id = id;
      this.color = color;
    }
  }

  public static void Main(String[] args) {
    CAR one = new CAR(4, "red");
    CAR two = new CAR(4, "blue");
    CAR three = new CAR(6, "blue");

    List<CAR> cars = new List<CAR>();
    cars.Add(one);
    cars.Add(two);
    cars.Add(three);

    List<CAR> distinct_c = cars.GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
    for (int i = 0; i < distinct_c.Count(); i++) {
      Console.Write(distinct_c[i].id + " ");
    }
  }
}

Where 조건을 추가하여 p.id가 null이 아닌지 확인한 다음 호출할 수도 있습니다.

List<CAR> distinct_c =
    cars.Where(p => p.id != null).GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
for (int i = 0; i < distinct_c.Count(); i++) {
  Console.Write(distinct_c[i].id + " ");
}

결과도 마찬가지일 것입니다.

C#에서 First()를 사용할 때 고려할 사항

경우에 따라 FirstorDefault()를 사용할 수 있습니다. First()와 동일한 기능을 수행하지만 첫 번째 요소가 없으면 기본값을 반환하는 또 다른 함수입니다.

null 값에서 오류를 해결하는 데 사용할 수 있습니다.

DistinctBy를 사용하여 C#의 하나 이상의 속성을 기반으로 고유한 목록 얻기

C#에서 고유한 값을 반환할 수 있는 함수를 작성할 수 있습니다.

한 가지 방법은 키와 값을 가져와 함께 매핑할 수 있는 해시 테이블을 사용하는 것입니다. 다음과 같은 함수를 작성할 수 있습니다.

public static IEnumerable<S> DistinctBy<S, K>(this IEnumerable<S> source, Func<S, K> keySelector) {
  HashSet<K> seen = new HashSet<K>();
  foreach (S element in source) {
    if (seen.Add(keySelector(element))) {
      yield return element;
    }
  }
}

그러나 그 전에 MORELINQ를 다운로드하고 코드에 맞게 구성해야 합니다.

var q = cars.DistinctBy(p => p.id);

그런 다음 이 변수 q의 내용을 인쇄하고 답을 얻을 수 있습니다. 전체 코드는 다음과 같습니다.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using MoreLinq;

namespace jinlku_console {
  static class pointer {
    class CAR {
      public int id;
      public string color;

      public CAR(int id, string color) {
        this.id = id;
        this.color = color;
      }
    }

    public static IEnumerable<S> DistinctBy<S, K>(this IEnumerable<S> source,
                                                  Func<S, K> keySelector) {
      HashSet<K> seen = new HashSet<K>();
      foreach (S element in source) {
        if (seen.Add(keySelector(element))) {
          yield return element;
        }
      }
    }

    public static void Main(String[] args) {
      CAR one = new CAR(4, "red");
      CAR two = new CAR(4, "blue");
      CAR three = new CAR(6, "blue");

      List<CAR> cars = new List<CAR>();
      cars.Add(one);
      cars.Add(two);
      cars.Add(three);

      var q = cars.DistinctBy(p => p.id);

      Console.WriteLine(q.Count());

      List<CAR> distinct_c = cars.GroupBy(p => (p.id, p.color)).Select(g => g.First()).ToList();
      for (int i = 0; i < distinct_c.Count(); i++) {
        Console.Write(distinct_c[i].id + " ");
      }
    }
  }
}

C#에서 하나 이상의 속성을 기반으로 고유한 목록을 얻는 또 다른 간단한 솔루션

동일한 쿼리를 작성하는 다른 방법은 다음과 같습니다.

var un = from car in cars group car by new(car.id) into mg select mg.First();

그러나 이를 사용하려면 언어를 9.0 이상으로 업데이트해야 할 수 있습니다.