-
[프렉티컬 C#] 배열과 List<T>Development/C# 2023. 7. 26. 15:15728x90
여러 요소를 한꺼번에 관리할 수 있게 해주는 데이터 구조는 배열과 컬렉션이 있다.
컬렉션
- Group of objects
- Collections provide a more flexible way to work with groups of objects. Unlike arrays, the group of objects you work with can grow and shrink dynamically as the needs of the application change.
컬렉션 종류
Dictionary<TKey,TValue> 키에 따라 구성된 키/값 쌍의 컬렉션을 나타냅니다. List<T> 인덱스로 액세스할 수 있는 개체 목록을 나타냅니다. 목록의 검색, 정렬 및 수정에 사용할 수 있는 메서드를 제공합니다. Queue<T> FIFO(선입선출) 방식의 개체 컬렉션을 나타냅니다. SortedList<TKey,TValue> 연관된 IComparer<T> 구현을 기반으로 키에 따라 정렬된 키/값 쌍의 컬렉션을 나타냅니다. Stack<T> LIFO(후입선출) 방식의 개체 컬렉션을 나타냅니다. 차이점
배열
인스턴스를 생성할 때 저장할 수 있는 요소의 개수가 정해지고 나중에 수정 불가
컬렉션
인스턴스 생성 후 요소 추가, 삽입, 삭제 가능
공통점
둘 다 IEnumerable<T> 인터페이스를 가지고 있다.
Enumerable.Repeat 메서드
동일한 값이 반복되는 시퀀스를 생성한다.
* 연속된 IEnumerable<T>형 데이터를 시퀀스라고 한다.
var strings = Enumerable.Repeat(-1, 20) // -1을 20번 생성하라는 의미 .ToList(); // List<int>로 변환 var strings = Enumerable.Repeat("hi", 10) // "hi"를 10번 생성하라는 의미 .ToArray();
Enumerable.Range 메서드
1, 2, 3, ... 10 과 같이 연속되는 숫자값을 설정할 수 있다.
var array = Enumerable.Range(1, 20) // 두 번째 인수에는 생성할 개수를 지정 .ToArray();
Queryable.Average 메서드
숫자 값 시퀀스의 평균을 계산합니다.
Queryable.Sum 메서드
숫자 값 시퀀스의 합을 계산합니다.
Queryable.Min 메서드
최솟값을 구한다.
Queryable.Max 메서드
최댓값을 구한다.
Queryable.Count 메서드
시퀀스의 요소 수를 반환합니다.
Queryable.Any 메서드
- 조건에 일치하는 요소가 시퀀스에 존재하는지 여부를 조사한다.
- 조건에 일치하는 요소가 하나라도 발견되면 true 반환, 발견되지 않으면 false 반환
Queryable.All 메서드
- 시퀀스의 모든 요소가 특정 조건에 맞는지 확인한다.
- 시퀀스가 비어 있으면 항상 true 반환한다.
Queryable.SequenceEqual 메서드
두 시퀀스가 서로 같은지 확인합니다.
var num1 = new List<int> {1, 2, 3, 4, 5}; var num2 = new List<int> {1, 2, 3, 4, 5}; bool equal = num1.SequenceEqual(num2);
Queryable.FirstOrDefault 메서드
- 시퀀스의 첫 번째 요소를 반환하거나, 요소가 없으면 기본값을 반환한다.
- First 메서드는 조건을 만족하는 요소가 발견되지 않으면 InvaildOperation Exception 에외가 발생하지만,
FirstOrDefault 메서드는 default(T)의 값을 반환한다.
- 마지막 요소를 구하려면 Last 메서드나 LastDefault 메서드 사용
*수치형의 default(T)는 0이고 구조체의 default(T)는 각 멤버의 값이 해당 형에 따라 0이나 null이다. 참조형은 null
FindIndex 메서드
- 지정한 조건자에 정의된 조건과 일치하는 요소를 검색하여 일치하는 요소 중 첫 번째 요소의 인덱스(0부터 시작)를 반환한다.
- 조건이 일치하는 마지막 인덱스를 구할 때는 FindLastIndex 메서드 사용한다.
- FindIndex와 FindLastIndex 메서드는 배열과 List<T>에서만 사용할 수 있다.
Queryable.Where 메서드
조건자에 따라 값의 시퀀스를 필터링합니다.
Queryable.Take 메서드
- 시퀀스 시작 위치에서 지정된 수의 연속 요소를 반환한다.
- 지정한 개수만큼 없어도 오류를 발생시키지 않고 구할 수 있는 만큼의 요소를 구한다.
int[] grades = { 59, 82, 70, 56, 92, 98, 85 }; // Sort the grades in descending order and take the first three. IEnumerable<int> topThreeGrades = grades.AsQueryable().OrderByDescending(grade => grade).Take(3); Console.WriteLine("The top three grades are:"); foreach (int grade in topThreeGrades) Console.WriteLine(grade); /* This code produces the following output: The top three grades are: 98 92 85 */
Queryable.TakeWhile 메서드
- 지정된 조건이 만족하는 동안에만 시퀀스의 요소를 반환한다.
- 조건을 만족하지 않는 요소가 발견된 시점에서 열거가 종료된다.
Queryable.SkipWhile 메서드
- TakeWhile 메서드와 반대
- 지정된 조건을 만족하는 동안에는 요소를 건너뛰고 나머지 요소를 반환합니다.
- 조건을 만족하지 않는 요소가 발견된 시점에서 열거가 종료된다.
Queryable.Select 메서드
시퀀스의 각 요소를 새 폼에 투영합니다.
Queryable.Distinct 메서드
중복된 요소를 제거한다.
Queryable.OrderBy 메서드
시퀀스의 요소를 오름차순으로 정렬합니다.
Queryable.OrderByDescending 메서드
시퀀스의 요소를 내림차순으로 정렬합니다.
Queryable.Concat 메서드
두 시퀀스를 연결합니다.
✓ foreach나 for 루프 안에서 리스트에 있는 요소를 삭제하면 안 된다.
// InvalidOperation Exception 예외 발생 List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; foreach (int n in list) { if (n % 4 == 0) list.Remove(n); }
연습문제
문제 6.1
var numbers = new int[] { 5, 10, 17, 9, 3, 21, 10, 40, 21, 3, 35 }; // 1 var max = numbers.Max(); Console.WriteLine(max); // 2 var standardIndex = numbers.Length - 2; var last2Num = numbers.Where((w, i) => i >= standardIndex); Console.WriteLine(String.Join(',', last2Num)); // 3 var strArray = numbers.Select(s => s.ToString()); Console.WriteLine(String.Join(',', strArray)); // 4 var alignedArray = numbers.OrderBy(x => x).Where((s, i) => i < 3); Console.WriteLine(String.Join(',', alignedArray)); // 5 var noDuplicationCount = numbers.Distinct().Count(c => c > 10); Console.WriteLine(noDuplicationCount);
리뷰
2. 예제 코드 보면서 이렇게 할 수 도 있구나 확인하기
4. Take 메서드 안 익숙해서 코드 작성할 때 생각이 안 난다. Take 메서드 기억하기!
예제 코드
class Program { static void Main(string[] args) { var numbers = new int[] { 5, 10, 17, 9, 3, 21, 10, 40, 21, 3, 35 }; Exercise1_1(numbers); Console.WriteLine("-----"); Exercise1_2(numbers); Console.WriteLine("-----"); Exercise1_3(numbers); Console.WriteLine("-----"); Exercise1_4(numbers); Console.WriteLine("-----"); Exercise1_5(numbers); } private static void Exercise1_1(int[] numbers) { var max = numbers.Max(); Console.WriteLine(max); } private static void Exercise1_2(int[] numbers) { var skip = numbers.Length - 2; foreach (var n in numbers.Skip(skip)) Console.WriteLine(n); } private static void Exercise1_3(int[] numbers) { var strs = numbers.Select(n => n.ToString()); foreach (var s in strs) Console.WriteLine(s); } private static void Exercise1_4(int[] numbers) { foreach (var n in numbers.OrderBy(n => n).Take(3)) Console.WriteLine(n); } private static void Exercise1_5(int[] numbers) { var count = numbers.Distinct().Count(n => n > 10); Console.WriteLine(count); } }
문제 6.2
class Program { static void Main(string[] args) { var books = new List<Book> { new Book { Title = "C# 프로그래밍의 상식", Price = 38000, Pages = 378 }, new Book { Title = "람다식과 LINQ의 비밀", Price = 25000, Pages = 312 }, new Book { Title = "원더풀 C# 라이프", Price = 29000, Pages = 385 }, new Book { Title = "독학 병렬처리 프로그래밍", Price = 48000, Pages = 464 }, new Book { Title = "구문으로 배우는 C# 입문", Price = 53000, Pages = 604 }, new Book { Title = "나도 할 수 있는 ASP.NET MVC", Price = 32000, Pages = 453 }, new Book { Title = "재미있는 C# 프로그래밍 교실", Price = 25400, Pages = 348 }, }; // 1 var array1 = books.Where(w => w.Title == "원더풀 C# 라이프").Select(s => new { s.Price, s.Pages }).FirstOrDefault(); Console.WriteLine($"가격 = {array1.Price}, 페이지 수 = {array1.Pages}"); // 2 var array2 = books.Count(c => c.Title.Contains("C#")); Console.WriteLine(array2); // 3 var array3 = books.Where(c => c.Title.Contains("C#")).Average(a => a.Pages); Console.WriteLine(array3); // 4 var array4 = books.FirstOrDefault(s => s.Price >= 40000); Console.WriteLine(array4.Title); // 5 var array5 = books.Where(w => w.Pages < 40000).Max(m => m.Pages); Console.WriteLine(array5); // 6 var array6 = books.Where(w => w.Pages >= 400).OrderByDescending(o => o.Price); foreach (var item in array6) { Console.WriteLine(item.Title, item.Price); } // 6 var array7 = books.Where(w => w.Title.Contains("C#") && w.Pages <= 500); foreach (var item in array7) { Console.WriteLine(item.Title); } } } class Book { public string Title { get; set; } public int Price { get; set; } public int Pages { get; set; } }
리뷰
1.
var array1 = books.Where(w => w.Title == "원더풀 C# 라이프").Select(s => new { s.Price, s.Pages }).FirstOrDefault();
아래 코드 처럼 쓸 걸 왜 더 복잡하게 작성했지?!
var array1 = books.FirstOrDefault(w => w.Title == "원더풀 C# 라이프");
예제 코드
class Program { static void Main(string[] args) { var books = new List<Book> { new Book { Title = "C# 프로그래밍의 상식", Price = 38000, Pages = 378 }, new Book { Title = "람다식과 LINQ의 비밀", Price = 25000, Pages = 312 }, new Book { Title = "원더풀 C# 라이프", Price = 29000, Pages = 385 }, new Book { Title = "독학 병렬처리 프로그래밍", Price = 48000, Pages = 464 }, new Book { Title = "구문으로 배우는 C# 입문", Price = 53000, Pages = 604 }, new Book { Title = "나도 할 수 있는 ASP.NET MVC", Price = 32000, Pages = 453 }, new Book { Title = "재미있는 C# 프로그래밍 교실", Price = 25400, Pages = 348 }, }; Exercise2_1(books); Console.WriteLine("-----"); Exercise2_2(books); Console.WriteLine("-----"); Exercise2_3(books); Console.WriteLine("-----"); Exercise2_4(books); Console.WriteLine("-----"); Exercise2_5(books); Console.WriteLine("-----"); Exercise2_6(books); Console.WriteLine("-----"); Exercise2_7(books); } private static void Exercise2_1(List<Book> books) { var book = books.FirstOrDefault(b => b.Title == "원더풀 C# 라이프"); if (book != null) Console.WriteLine("{0} {1}", book.Price, book.Pages); } private static void Exercise2_2(List<Book> books) { int count = books.Count(b => b.Title.Contains("C#")); Console.WriteLine(count); } private static void Exercise2_3(List<Book> books) { var average = books.Where(b => b.Title.Contains("C#")) .Average(b => b.Pages); Console.WriteLine(average); } private static void Exercise2_4(List<Book> books) { var book = books.FirstOrDefault(b => b.Price >= 4000); if (book != null) Console.WriteLine(book.Title); } private static void Exercise2_5(List<Book> books) { var pages = books.Where(b => b.Price < 4000) .Max(b => b.Pages); Console.WriteLine(pages); } private static void Exercise2_6(List<Book> books) { var selected = books.Where(b => b.Pages >= 400) .OrderByDescending(b => b.Price); foreach (var book in selected) { Console.WriteLine("{0} {1}", book.Title, book.Price); } } private static void Exercise2_7(List<Book> books) { var selected = books.Where(b => b.Title.Contains("C#") && b.Pages <= 500); foreach (var book in selected) Console.WriteLine(book.Title); } } class Book { public string Title { get; set; } public int Price { get; set; } public int Pages { get; set; } }
728x90'Development > C#' 카테고리의 다른 글
[C#] 인덱서 (0) 2023.07.27 [프렉티컬 C#] Dictionary (0) 2023.07.27 [프렉티컬 C#] 문자열 처리 (0) 2023.07.26 [프렉티컬 C# 연습문제] 2부 - 1장 (0) 2023.07.25 [프랙티컬 C# 연습문제] 1부 - 3장 (0) 2023.07.15