CodeGym /행동 /C# SELF /요소 필터링

요소 필터링

C# SELF
레벨 29, 레슨 0
사용 가능

1. 컬렉션 필터링의 기본 방법

필터링은 금 캐는 체랑 비슷한 거야. 금덩이 대신 우리가 원하는 요소만 컬렉션에서 골라내는 거지. 예를 들어, 사용자 리스트가 있는데, 성인만 찾고 싶거나, 학생만, 아니면 커피 좋아하는 사람(프로그래머지 뭐)만 찾고 싶을 때. 이렇게 원하는 요소만 뽑아내는 건 진짜 자주 쓰여. DB 작업이든, 사용자 입력 처리든 어디서나 나와.

C#에서 필터링하는 여러 방법을 같이 볼 거야. 배우면서 우리 콘솔 학습 앱에 필터를 하나씩 추가해볼 거고.

루프를 이용한 수동 필터링

가장 쉽고 고전적인 방법부터 시작하자: foreach로 필터링하기:


// 예시: 숫자 리스트에서 짝수만 고르기

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
List<int> evenNumbers = new List<int>();

foreach (int number in numbers)
{
    if (number % 2 == 0) // 만약 숫자가 짝수면
    {
        evenNumbers.Add(number);
    }
}

Console.WriteLine("짝수:");
foreach (int n in evenNumbers)
{
    Console.WriteLine(n);
}

이런 방식은 항상 잘 돌아가고, 이해하기도 쉽지만, 엄청 간단하거나 "요즘 스타일"은 아니야.

왜 수동 필터링이 항상 편한 건 아닐까?

컬렉션이 달라지거나, 필터 조건이 바뀌거나, 여러 필터를 한 번에 써야 하면 비슷한 코드가 엄청 많아져. 좀 더 간결하고, 읽기 쉽고, 모듈화된 코드가 땡기지.

2. 복잡한 기준으로 필터링

이번엔 객체 컬렉션이 있다고 해보자. 우리 앱에서 쓰는 사용자 예시로 가자.


public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsStudent { get; set; }
}

사용자 리스트 선언:


List<User> users = new List<User>
{
    new User { Name = "아냐", Age = 17, IsStudent = true },
    new User { Name = "보리스", Age = 21, IsStudent = false },
    new User { Name = "비카", Age = 19, IsStudent = true },
    new User { Name = "글렙", Age = 25, IsStudent = false }
};

예시 1: 모든 학생 고르기


List<User> students = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent)
        students.Add(user);
}

Console.WriteLine("학생 리스트:");
foreach (User user in students)
{
    Console.WriteLine($"{user.Name} ({user.Age})");
}

예시 2: 성인 학생만 고르기


List<User> adults = new List<User>();
foreach (User user in users)
{
    if (user.Age >= 18 && user.IsStudent)
        adults.Add(user);
}

Console.WriteLine("성인 학생:");
foreach (User user in adults)
{
    Console.WriteLine($"{user.Name} ({user.Age})");
}

필터 조건이 동적으로 바뀌면?

필터 조건을 따로 메서드로 빼서, 루프 안에서 호출할 수도 있어:


bool IsAdult(User u) { return u.Age >= 18; }
bool IsStudent(User u) { return u.IsStudent; }

List<User> filtered = new List<User>();
foreach (User user in users)
{
    if (IsAdult(user) && IsStudent(user))
        filtered.Add(user);
}

3. 딕셔너리에서 키로 필터링

리스트나 배열도 좋지만, 딕셔너리도 자주 써.

예를 들어, 키는 사용자 이름, 값은 나이인 딕셔너리가 있다고 해보자:


Dictionary<string, int> ageByName = new Dictionary<string, int>
{
    ["아냐"] = 17,
    ["보리스"] = 21,
    ["비카"] = 19,
    ["글렙"] = 25
};

문제: 18살 이상만 고르기


Dictionary<string, int> adults = new Dictionary<string, int>();
foreach (var pair in ageByName)
{
    if (pair.Value >= 18)
        adults.Add(pair.Key, pair.Value);
}

Console.WriteLine("성인:");
foreach (var pair in adults)
{
    Console.WriteLine($"{pair.Key}: {pair.Value}살");
}

문제: 이름이 'В'로 시작하는 사용자만 고르기


Dictionary<string, int> namesWithV = new Dictionary<string, int>();
foreach (var pair in ageByName)
{
    if (pair.Key.StartsWith("В"))
        namesWithV.Add(pair.Key, pair.Value);
}

Console.WriteLine("'В'로 시작하는 이름:");
foreach (var pair in namesWithV)
{
    Console.WriteLine($"{pair.Key}: {pair.Value}살");
}

4. 필터링 원리

필터링 과정은 이렇게 돌아가


┌──────────────────────────────────┐
│  리스트: [1, 2, 3, 4, 5, 6]      │
└──────────────────────────────────┘
         │
         ▼
    [검사: n % 2 == 0]
         │
         ▼
┌──────────────────────────────────┐
│  결과: [2, 4, 6]                 │
└──────────────────────────────────┘

필터 조합: 여러 조건으로 필터링

데이터를 단계별로 뽑고 싶으면 연속적으로 필터링할 수도 있어:


// 먼저 학생만 필터링
List<User> onlyStudents = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent)
        onlyStudents.Add(user);
}

// 그중에서 성인만 고르기
List<User> adultStudents = new List<User>();
foreach (User user in onlyStudents)
{
    if (user.Age >= 18)
        adultStudents.Add(user);
}

아니면 한 번에 다 해도 돼:


List<User> adultStudents = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent && user.Age >= 18)
        adultStudents.Add(user);
}

정렬과 다른 작업들

정렬은 리스트의 Sort 메서드로 할 수 있어:


// 나이순으로 정렬된 성인 학생
adultStudents.Sort((a, b) => a.Age.CompareTo(b.Age));

정렬은 다음 강의에서 더 자세히 다룰 거야!

5. 사용자 시나리오에서의 필터링

1. 사용자 입력 필터링

예를 들어, 우리 앱이 점수 리스트를 입력받고, "5점"만 골라야 한다고 해보자.


Console.Write("점수를 공백으로 입력하세요: ");
string input = Console.ReadLine();

List<int> grades = new List<int>();
foreach (string s in input.Split(' '))
{
    if (int.TryParse(s, out int grade))
        grades.Add(grade);
}

List<int> fives = new List<int>();
foreach (int grade in grades)
{
    if (grade == 5)
        fives.Add(grade);
}

Console.WriteLine("5점:");
foreach (var grade in fives)
{
    Console.WriteLine(grade);
}

2. 여러 조건으로 필터링

문제: 18~22살(포함) 학생만 고르기.


List<User> filtered = new List<User>();
foreach (User user in users)
{
    if (user.IsStudent && user.Age >= 18 && user.Age <= 22)
        filtered.Add(user);
}

3. 특정 요소 포함 여부로 필터링

문자열 리스트에서 ".net"이 들어간 것만(대소문자 무시) 고르기.


List<string> technologies = new List<string> { "C#", ".NET", "Java", "dotnet", "JavaScript" };

List<string> netTechs = new List<string>();
foreach (var tech in technologies)
{
    if (tech.ToLower().Contains(".net"))
        netTechs.Add(tech);
}

foreach (var tech in netTechs)
{
    Console.WriteLine(tech);
}

6. 필터링의 특징과 흔한 실수

필터링은 쉬워 보여도, 실수할 수 있는 부분이 있어. 몇 가지 특징을 같이 보자.

원본 컬렉션 변경

필터링한 다음에 원본 컬렉션을 바꿔도, 이미 새 리스트를 만들었다면 결과는 안 바뀌어. 근데 그냥 원래 리스트 참조만 저장했다면, 원본이 바뀌면 결과도 바뀔 수 있어.


List<int> filtered = new List<int>();
foreach (int n in numbers)
{
    if (n > 2)
        filtered.Add(n);
}

// 원본 리스트에 값 추가
numbers.Add(10);

foreach (var n in filtered)
{
    Console.WriteLine(n); // 10은 여기 안 나와
}

수동 필터링 결과

수동 필터링 결과는 보통 새로운 변경 가능한 리스트(List<T>)야. 거기서 추가, 삭제 등 원하는 대로 할 수 있어.

필터링과 성능

루프에서 필터 함수는 컬렉션의 모든 요소마다 호출돼. 조건 함수가 무거우면 조심해야 해. 복잡한 로직이나 로그 남기거나 추가 작업이 필요하면 그냥 foreach로 직접 하는 게 더 나을 때도 있어.

2
과제
C# SELF, 레벨 29, 레슨 0
잠금
딕셔너리 값으로 필터링하기
딕셔너리 값으로 필터링하기
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION