LINQ: from 문 중첩

00·2024년 12월 29일

C#

목록 보기
88/149
using System;
using System.Linq;


/*
from 문 중첩:
여러 개의 데이터 원본에 질의(쿼리)하기
 */


// from 문을 중첩하면 여러 개의 데이터 원본에서 데이터를 쿼리할 수 있음을 보여줌
namespace FromFrom
{
    class Class // Name과 Score 프로퍼티를 가집니다.
                // Name은 문자열 타입이고, Score는 정수형 배열 타입입니다.
    {
        public string Name { get; set; }
        public int[] Score { get; set; }
    }

    class MainApp
    {
        static void Main(string[] args)
        {
            Class[] arrClass =
            {
                new Class(){Name="연두반", Score=new int[]{99, 80, 70, 24}},
                new Class(){Name="분홍반", Score=new int[]{60, 45, 87, 72}},
                new Class(){Name="파랑반", Score=new int[]{92, 30, 85, 94}},
                new Class(){Name="노랑반", Score=new int[]{90, 88, 0, 17}}
            };

            var classes = from c in arrClass // arrClass 객체에 from 절로 접근해서 범위 변수 c를 뽑고,
                          from s in c.Score // 다시 그 c 객체의 Score 필드에 또 다른 from 절로 접근해서
                                            // 새로운 범위 변수 s를 뽑습니다.
                                            // 범위 변수 s는 개별 점수를 나타냅니다.
                          where s < 60 // where 절을 사용해서 이 s가 60보다 낮은지 걸러내고,
                          orderby s
                          select new { c.Name, Lowest = s }; // new {...} 부분을 통해 무명 형식을 선언해서
                                                             // 낙제점을 맞은 학생의 학급 이름과 점수를 담아냅니다.

            foreach (var c in classes) // classes 쿼리 결과를 순회하면서 각 익명 객체를 c 변수에 할당합니다.
                Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})"); // c 변수를 통해 익명 객체의 Name과 Lowest 프로퍼티에 접근하여
                                                                    // "낙제 : {반 이름} ({낙제 점수})" 형식으로 출력합니다.
        }
    }
}


/*
출력 결과

낙제 : 노랑반 (0)
낙제 : 노랑반 (17)
낙제 : 연두반 (24)
낙제 : 파랑반 (30)
낙제 : 분홍반 (45)
*/

코드 설명

이 C# 코드는 LINQ의 from 문을 중첩하여 사용하는 방법을 보여주는 예제입니다. from 문을 중첩하면 여러 개의 데이터 원본에서 데이터를 쿼리할 수 있습니다.

Class 클래스는 NameScore 프로퍼티를 가집니다. Name은 문자열 타입이고, Score는 정수형 배열 타입입니다.

MainApp 클래스의 Main 메서드에서는 4개의 Class 객체를 생성하여 arrClass 배열에 저장합니다. 각 Class 객체는 반 이름과 학생들의 점수를 나타냅니다.

from c in arrClassarrClass 배열의 각 요소를 c라는 변수에 할당하며 쿼리를 시작합니다.

from s in c.Scorec 객체의 Score 배열의 각 요소를 s라는 변수에 할당하며 중첩된 쿼리를 시작합니다.

where s < 60s 값이 60보다 작은 경우, 즉 낙제 점수인 경우에만 요소를 선택합니다.

orderby s는 선택된 요소를 s 값을 기준으로 오름차순으로 정렬합니다.

select new { c.Name, Lowest = s }는 익명 형식을 사용하여 NameLowest 프로퍼티를 가진 새로운 객체를 생성합니다. Namec 객체의 Name 프로퍼티 값이고, Lowests 값입니다.

foreach (var c in classes)classes 쿼리 결과를 순회하며 각 요소를 c라는 변수에 할당합니다.

Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})");cNameLowest 프로퍼티 값을 출력합니다.

출력 결과

낙제 : 노랑반 (0)
낙제 : 노랑반 (17)
낙제 : 연두반 (24)
낙제 : 파랑반 (30)
낙제 : 분홍반 (45)

select new { c.Name, Lowest = s };
foreach (var c in classes)
Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})");

이 부분은 LINQ 쿼리 결과를 익명 형식으로 만들어서 낙제생 정보를 출력하는 부분입니다.

select new { c.Name, Lowest = s }; 에서 select는 쿼리 결과로 어떤 데이터를 선택할지 지정하는 키워드입니다. 여기서는 new { c.Name, Lowest = s } 부분을 통해 익명 형식을 사용하고 있습니다.

익명 형식은 이름이 없는 클래스와 같습니다. 컴파일러가 자동으로 클래스를 만들어 주고, 그 안에 c.NameLowest = s 두 개의 프로퍼티를 만들어서 낙제생 정보를 저장합니다.

c.Name은 현재 반의 이름을 나타내고, Lowest = s는 낙제 점수(s)를 Lowest라는 프로퍼티에 저장하는 것을 의미합니다.

foreach (var c in classes)classes 쿼리 결과를 순회하면서 각 익명 객체를 c 변수에 할당합니다.

Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})");c 변수를 통해 익명 객체의 NameLowest 프로퍼티에 접근하여 "낙제 : {반 이름} ({낙제 점수})" 형식으로 출력합니다.

이렇게 익명 형식을 사용하면 쿼리 결과를 간결하게 표현하고, 필요한 정보만 선택적으로 저장할 수 있습니다.

0개의 댓글