[c#] 클래스를 담고 있는 List 소트하기
리스트에 정수나 문자열 같이 하나의 데이터 타입만 담겨 있는 경우와 클래스처럼 구조화된 객체가 저장된 경우에는 소트를 하는 방법이 다르다. 전자의 경우에는 여러 소트 로직들을 바로 이용하면 되지만 후자의 경우에는 좀 더 복잡하다.
클래스를 엘리먼트로 하는 리스트를 소트하는 데에는 여러 방법들이 있다. 대표적인 방법들은 아래와 같다.
기본적으로 List.Sort 메서드를 이용하는 방법이 있다. 가장 빠르지만 코드가 길다. Sort 역시 다양한 방법들로 구현을 할 수 있는데 아래의 방법이 제일 간단하다.
아래의 예제에서 클래스는 iComparable 인터페이스를 상속한다. 그런 뒤 CompareTo 메서드를 이용하여 소트의 기준이 되는 필드를 지정한다. 아래의 코드는 오름차순이고 내림차순으로 하려면 class1!.Int.CompareTo(Int)으로 바꾸면 된다. 지정된 필드는 default comparer가 되었기 때문에 아규먼트 없이 그냥 Sort()라고만 하면 소트가 된다. 필드 말고 프라퍼티를 써도 된다.
class Class1 : IComparable<Class1>
{
public int Int;
public string? String;
public int CompareTo(Class1? class1)
{
return Int.CompareTo(class1!.Int); // ascend
//return class1!.Int.CompareTo(Int); descend
}
}
private void button1_Click(object sender, EventArgs e)
{
List<Class1> class1s = new();
class1s.Add(new Class1 { Int = 67890, String = "qwert" });
class1s.Add(new Class1 { Int = 12345, String = "abcde" });
class1s.Sort();
Text = class1s[0].Int.ToString(); // 12345
}
아래는 linq를 이용한 예제다. 클래스를 List에 담은 뒤 클래스의 Int 필드를 기준으로 List를 소트하는 예제다. 소트된 새로운 객체를 만들어야 한다.
class Class1
{
public int Int;
public string? String;
}
var sortedclass1s = from Class1 in class1s orderby Class1.Int select Class1;
Text = sortedclass1s.ToList()[0].Int.ToString(); // 12345
아래와 같이 람다를 이용할 수도 있다.
List<Class1> sortedclass1s = class1s.OrderBy(x => x.Int).ToList();
여기에서 x는 아규먼트를 뜻하는 임의의 문자다. 패러미터의 개수에 따라 x, y … 로 쓰는 게 관례이므로 다른 문자를 써도 된다.
=>는 어떤 메서드에 아규먼트가 들어가서 오른쪽의 값이 반환된다는 뜻이다. 위 예제에서는 클래스인 리스트 엘리먼트가 들어가서 그것의 필드인 Int를 반환하는 거다.