본문 바로가기
C#/Enumerable

[C#] Enumerable 클래스 (Linq)

by 스누ㅍl 2024. 7. 23.

최근 수정: 2024.08.21

Enumerable 클래스 내용 중 새로 알게되거나 사용했던 메서드들 기록하는 곳입니다.

 

Enumerable 클래스

Enumerable 클래스는 LINQ의 일부로 IEnumerable 인터페이스를 구현하는 컬렉션 클래스에 대한 LINQ 기능을 제공한다.

 

시퀀스

시퀀스는 순서가 있는 일련의 데이터를 나타내는 추상적인 개념

주요메서드

  • Range([시작 인덱스], [길이]) : 일정한 숫자 범위의 시퀀스를 만든다. 첫번째 매개변수가 시작 숫자이고, 두번째 매개 변수는 생성하려는 시퀀스의 길이 이다.
var sequence = Enumerable.Range(0, 10);
foreach(var num in sequence)
{
    Console.Write(num); // 0123456789
}

 

  • Repeat([정수], [반복할 횟수]) : 첫번째 매개변수로 받은 정수를 두번째 매개변수로 받은 수만큼 반복한 시퀀스를 반환한다.
int[] arr = Enumerable.Repeat(3, 3).ToArray();
Console.WriteLine(string.Join(",", arr)); // 3, 3, 3

 

  • ToArray() : 시퀀스를 배열로 만들어준다. 시퀀스를 메서드를 통해 조작해준 뒤 마지막으로 ToArray() 메서드를 사용하면 배열로 반환할 수 있다.
var sequence = Enumerable.Range(1, 9);
int[] odd = sequence.Where(num => num % 2 == 1).ToArray(); // where메서드로 반환된 시퀀스를 배열로

foreach(int num in odd)
{
    Console.Write(num); // 13579
}

 

  • Sum() :시퀀스 내부의 숫자들의 합을 반환해 준다.
int sum = Enumerable.Range(1, 5).Sum(); // 1+2+3+4+5
Console.WriteLine(sum); // 15

 

  • Reverse() : 시퀀스를 반대로 뒤집어 준다.
int[] answer = Enumerable.Range(3, 8).Reverse().ToArray();

foreach(int i in answer)
    Console.Write(i + " "); // 10 9 8 7 6 5 4 3

 

  • Skip([스킵할 개수]) : 매개변수로 받은 수 만큼 스킵하고 시퀀스를 반환한다.
int[] arr = { 1, 2, 3, 4, 5, 6 };

int[] skipArr = arr.Skip(2).ToArray();

Console.WriteLine(string.Join(", ", skipArr)); // 3, 4, 5, 6

 

  • Take([가져올 개수]) : 처음부터 매개변수로 받은 수 만큼 시퀀스를 반환한다.
int[] arr = { 1, 2, 3, 4, 5, 6 };

int[] skipArr = arr.Take(2).ToArray();

Console.WriteLine(string.Join(", ", skipArr)); // 1, 2

 

  • SequenceEqual([비교할 시퀀스]) : 시퀀스의 크기와 각 인덱스별 요소가 전부 일치하는지 여부를 반환해준다.
int[] arr1 = { 1, 2, 3, 4, 5 };
int[] arr2 = { 0, 1, 2, 3, 4 };
int[] arr3 = { 1, 2, 3, 4, 5 };

Console.WriteLine(arr1.SequenceEqual(arr2)); // False
Console.WriteLine(arr1.SequenceEqual(arr3)); // True

 

  • Except([제외할 값이 담긴 시퀀스]) : 시퀀스에 담긴 값을 제외한 시퀀스를 반환해준다.
int[] arr = { 0, 1, 2, 3, 4, 5 };
int[] delete_list = { 1, 3, 5 };

int[] exceptArr = arr.Except(delete_list).ToArray();

Console.WriteLine(string.Join(",", exceptArr)); // 0,2,4

 

  • Average() : 시퀀스에 담긴 요소들의 평균을 반환해준다.
int[] arr = { 1, 2, 3, 4 };

Console.WriteLine(arr.Average()); // 2.5

 

  • ElementAt(index) : 해당 인덱스 요소를 반환한다.
int[] arr = { 4, 21, 27, 32, 47, 11 };

// arr를 오름차순으로 정렬 후 index 2에 해당하는 요소 반환
int num = arr.OrderBy(o => o).ElementAt(2);

Console.WriteLine(num); // 21

 

  • Distinct() : 시퀀스 내부의 중복 값을 제거한 시퀀스를 반환한다.
int[] arr = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };

arr = arr.Distinct().ToArray();

Console.WriteLine(string.Join(",", arr)); // 1,2,3,4

람다식 메서드

  • Select() :  각 요소를 요청에 맞게 만들어 새로운 시퀀스를 만들어 준다.
    예를 들면 각 요소의 타입을 변경한다던지, 특정 프로퍼티만 추출한다던지, 각 요소에 연산을 한다던지 등등
string[] intStrs = { "123", "456", "789" };

int[] answer = intStrs.Select(s => int.Parse(s)).ToArray(); // 각 요소를 정수로 바꾸기

foreach (int i in answer)
    Console.Write(i + " "); // 123 456 789

 

  • Where() : 특정 조선을 만족하는 요소만 선택해서 새로운 시퀀스를 만든다.
var sequence = Enumerable.Range(1, 9);
var even = sequence.Where(num => num % 2 == 0);

foreach(var num in even)
{
    Console.Write(num); // 2468
}

 

※ 인덱스 활용

Select(), Where()은 두번째 매개변수로 인덱스를 가진다. 이를 활용하면 다양한 코드를 작성할 수 있다.

string[] arr = { "a", "b", "c", "d", "e" };

string[] whereArr = arr.Where((w, index) => index % 2 == 0).ToArray();
foreach (string str in whereArr)
    Console.Write(str + " "); // a c e

int[] selectArr = arr.Select((s, index) => index).ToArray();
foreach(int i in selectArr)
    Console.Write(i + " "); // 0 1 2 3 4

 

  • OrderBy() : 시퀀스의 요소를 오름차순으로 정렬한다.
  • OrderByDescending() : 시퀀스의 요소를 내림차순으로 정렬한다.
int[] num_list = { 12, 4, 15, 46, 38, 1, 14, 56, 32, 10 };
int[] asc_num_list = num_list.OrderBy(o => o).ToArray();
int[] desc_num_list = num_list.OrderByDescending(o => o).ToArray();

foreach (int i in asc_num_list) 
    Console.Write(i + " "); // 1 4 10 12 14 15 32 38 46 56

foreach (int i in desc_num_list)
    Console.Write(i + " "); // 56 46 38 32 15 14 12 10 4 1

 

  • Aggregate() : 각 요소를 누적해서 연산을 처리해서 반환한다.
    (현재값, 연산할 값) => 연산, 이런식으로 사용이 가능하다.
    첫번째 매개변수로 초기값을 줄수도 있다. 없으면 시퀀스의 첫번째 요소가 초기값이 된다.
int[] num_list = { 1, 2, 3, 4, 5 };

int result = num_list.Aggregate((cur, next) => cur * next);
Console.WriteLine(result); // 120

// 초기값 0, 홀수만 더하기
result = num_list.Aggregate(0, (cur, next) => (next%2==1) ? cur+next : cur);
Console.WriteLine(result); // 9

 

  • GroupBy() : 그룹을 지어 key-value형태로 시퀀스를 반환한다.
string[] strArr = { "a", "bc", "d", "efg", "hi" };

var arr = strArr.GroupBy(g => g.Length); // 각 요소의 길이를 기준으로 그룹
// index : key : value
// 0 : 1 : [ "a", "d" ]
// 1 : 2 : [ "bc", "hi" ]
// 2 : 3 : [ "efg" ]

// 각 요소의 key값을 출력
Console.WriteLine(string.Join(",", arr.Select(s => s.Key))); // 1,2,3

 

  • Zip() : 두 시퀀스를 이용하여 하나의 결과 시퀀스를 반환해준다.
    시퀀스1.Zip(시퀀스2, (시퀀스1요소, 시퀀스2요소) => 계산식) : 계산식을 통한 결과값의 시퀀스를 반환
int[] a = { 1, 2, 3, 4 };
int[] b = { -3, -1, 0, 2 };

// a, b 배열의 요소들을 순서대로 곱해서 반환
int[] answer = a.Zip(b, (n1, n2) => n1 * n2).ToArray();

Console.WriteLine(string.Join(",", answer)); // -3,-2,0,8
Console.WriteLine(answer.Sum()); // 3