111. SortedList와 SortedList<TKey, TValue>
using System;
using System.Collections.Generic;
namespace P111
{
class Program
{
static void Main(string[] args)
{
SortedList<int, string> s1 = new SortedList<int, string>();
s1.Add(3, "C");
s1.Add(4, "D");
s1.Add(1, "A");
s1.Add(2, "B");
for (int i = 0; i < s1.Count; i++) Console.WriteLine(s1.Keys[i] + " " + s1.Values[i]);
Console.WriteLine();
foreach (var v in s1 ) Console.WriteLine(v);
SortedList<string, int> s2 = new SortedList<string, int>();
s2.Add("A", 1);
s2.Add("B", 2);
s2.Add("C", 3);
s2.Add("D", 4);
Console.WriteLine(s2["C"]);
int val;
if (s2.TryGetValue("A", out val)) Console.WriteLine("A : "+val);
Console.WriteLine(s2.ContainsKey("C"));
Console.WriteLine(s2.ContainsValue(2));
s2.Remove("A");
s2.RemoveAt(2);
foreach (var v in s2) Console.WriteLine($"{v, -10}");
}
}
}
결과
1 A
2 B
3 C
4 D
[1, A]
[2, B]
[3, C]
[4, D]
3
A : 1
True
True
[B, 2]
[C, 3]
딕셔너리와 비슷하게 key와 value를 가진 클래스, SortedList이다.
코드가 보여주는 것은 사용법과, TryGetValue같은 매소드 들이다.
아이템창에서 퀘스트 아이템이 있는지 검사하는 매커니즘에 사용하면 좋을 것 같다.
112. 인덱서
using System;
namespace P112
{
class MyCollection<T>
{
private T[] arr = new T[100];
public T this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}
}
class Program
{
static void Main(string[] args)
{
var myString = new MyCollection<string>();
myString[0] = "A";
myString[1] = "B";
myString[2] = "C";
for (int i = 0; i < 3 ; i++)
Console.WriteLine(myString[i]);
}
}
}
결과
A
B
C
array를 프로그래머가 직접 구현하는 형태인 것 같다.
이걸 인덱서라고 하는데, 인스턴스 내의 데이터에 접근하는 방법이라고 한다.
핵심은 클래스 같은 요소도 배열처럼 사용할 수 있게 해주는 것에 있다.
113. Delegate의 기본, 배열에서 홀수와 짝수 찾기
using System;
namespace P113
{
class Program
{
delegate bool MemberTest(int a);
static void Main(string[] args)
{
int[] arr = new int[] { 3, 5, 4, 2, 6, 4, 6, 8, 54, 23, 4, 6, 4 };
Console.WriteLine("Odd");
Console.WriteLine(Count(arr, IsOdd));
Console.WriteLine("Even");
Console.WriteLine(Count(arr, IsEven));
}
static int Count(int[] a, MemberTest testMethod)
{
int cnt = 0;
foreach (var n in a)
{
if ( testMethod(n)) cnt++;
}
return cnt;
}
public static bool IsOdd(int n) { return n % 2 != 0; }
public static bool IsEven(int n) { return n % 2 == 0; }
}
}
결과
Odd
3
Even
10
내가 C#을 공부하게 만든 원인 3이다.
함수2개를 한번에 사용할 수 있게 해주는 클래스이다.
대충 정리하면
static int Count(int[] a, MemberTest testMethod)에서 testMethod에
public static bool IsOdd(int n) { return n % 2 != 0; }
public static bool IsEven(int n) { return n % 2 == 0; }
이 2개의 메소드를 심어서 사용하는 형태가 된다.
114. 이름 없는 델리게이트
using System;
namespace P114
{
class Program
{
delegate bool MemberTest(int a);
static void Main(string[] args)
{
var arr = new[] { 3, 5, 4, 2, 6, 4, 6, 8, 54, 23, 4, 6, 4 };
Console.WriteLine("Odd");
int n = Count(arr, delegate (int x) { return x % 2 == 0; });
Console.WriteLine(n);
Console.WriteLine("Even");
n = Count(arr, delegate (int x) { return x % 2 != 0; });
Console.WriteLine(n);
}
static int Count(int[] a, MemberTest testMethod)
{
int cnt = 0;
foreach (var n in a)
{
if (testMethod(n)) cnt++;
}
return cnt;
}
}
}
결과
Odd
3
Even
10
113에서는 delegate에서 메소드를 작성해서 넣었지만, 현재 코드처럼 람다식처럼 직접적으로 메소드 내에서 필요한 메소드를 정의해서 사용할 수 있음을 보여준다.
115. Func와 Action으로 델리게이트를 더 간단히 만들기
using System;
namespace P115
{
class Program
{
static void Main(string[] args)
{
var arr = new[] { 3, 5, 4, 2, 6, 4, 6, 8, 54, 23, 4, 6, 4 };
Console.WriteLine("Odd");
int n = Count(arr, delegate (int x) { return x % 2 == 0; });
Console.WriteLine(n);
Console.WriteLine("Even");
n = Count(arr, delegate (int x) { return x % 2 != 0; });
Console.WriteLine(n);
}
static int Count(int[] a, Func<int, bool> testMethod)
{
int cnt = 0;
foreach (var n in a)
{
if (testMethod(n)) cnt++;
}
return cnt;
}
}
}
결과는 113 114와 같기에 생략
delegate 객체 조차 귀찮은 경우를 위한 Func<>이다.
Func<int, bool>이 부분이 delagate를 대체하게 된다.
116. 람다식
using System;
namespace P116
{
class Program
{
static void Main(string[] args)
{
var arr = new[] { 3, 5, 4, 2, 6, 4, 6, 8, 54, 23, 4, 6, 4 };
Console.WriteLine("Odd");
int n = Count(arr, x => x % 2 == 0);
Console.WriteLine(n);
Console.WriteLine("Even");
n = Count(arr, x => x % 2 != 0);
Console.WriteLine(n);
}
static int Count(int[] a, Func<int, bool> testMethod)
{
int cnt = 0;
foreach (var n in a)
{
if (testMethod(n)) cnt++;
}
return cnt;
}
}
}
결과는 같이에 생략
delegate (int x) { return x % 2 != 0; }를 람다식으로 사용하여
x => x % 2 != 0 과 같은 형태로 생략하는 예시를 보여준다.
117. 람다식의 사용
1. 식람다
연산자의 오른쪽에 식이 있는 형태
A a = () => Code...
2. 문람다
중괄호 안에 문장을 지정함
A a = name => {};...
using System;
namespace P117
{
class Program
{
delegate double CalcMethod(double a, double b);
delegate bool IsTeenAger(Student student);
delegate bool IsAdult(Student student);
static void Main(string[] args)
{
Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
int[] numbers = { 2, 3, 4, 5 };
var squaredNumbers = numbers.Select(x => x * x);
Console.WriteLine(string.Join(" ", squaredNumbers));
Action line = () => Console.WriteLine();
line();
CalcMethod add = (a, b) => a + b;
CalcMethod subtract = (a, b) => a - b;
Console.WriteLine(add(10, 20));
Console.WriteLine(subtract(10.5, 20));
IsTeenAger isTeen = delegate (Student s) { return s.Age > 12 && s.Age < 20; };
Student s1 = new Student() { Name = "A", Age = 18 };
Console.WriteLine(isTeen(s1) ? "청소년" : "청소년 아님");
}
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
}
}
결과
25
4 9 16 25
30
-9.5
청소년
적극적으로 람다식을 코드에 사용한 예시를 보여준다.
118. Predicate<T> 델리게이트
using System;
namespace P118
{
class Program
{
static void Main(string[] args)
{
Predicate<int> isEven = n => n % 2 == 0;
Console.WriteLine(isEven(6));
Predicate<string> Lower = s => s.Equals(s.ToLower());
Console.WriteLine(Lower("Test"));
}
}
}
결과
True
False
메소드를 넣어서 쉽게 사용할 수 있게 해주는 Predicate<>델리게이트이다.
<> 변수명 = () 이 부분에 메소드를 넣으면 되는데, 보통 람다식으로 작성하여 간결화 하는 것 같다.
119. List<T>에서 Predicate<T>델리게이트 사용
using System;
namespace P119
{
class Program
{
static void Main(string[] args)
{
List<string> myList = new List<string>() { "mouse", "cow", "tiger", "rabbit", "dragon", "snake" };
bool n = myList.Exists(s => s.Contains("x"));
Console.WriteLine(n);
string name = myList.Find(s => s.Length == 3);
Console.WriteLine(name);
List<string>nameL = myList.FindAll(s => s.Length >= 3);
foreach(var v in nameL)
Console.WriteLine(v + " ");
}
}
}
결과
False
cow
mouse
cow
tiger
rabbit
dragon
snake
List<>로 생성한 객체에 predicate를 사용해보는 예시 코드이다.
람다식으로 주로 사용하며, List에 조건을 쉽게 줄 수 있는 것이 장점 같다.
120. LINQ의 기초
using System;
using System.Collections.Generic;
using System.Linq;
namespace P120
{
class Program
{
static void Main(string[] args)
{
List<int> data = new List<int>() { 123, 45, 12, 89, 456, 1, 4, 74, 46 };
List<int> lsSortedEven = new List<int>();
foreach (var i in data) if(i % 2 == 0) lsSortedEven.Add(i);
lsSortedEven.Sort();
foreach (var i in lsSortedEven)
{
Console.Write(i + " ");
}
Console.WriteLine();
var sortedEven = from i in data
where i % 2 == 0
orderby i
select i;
foreach (var i in sortedEven)
{
Console.Write(i + " ");
}
Console.WriteLine();
}
}
}
결과
4 12 46 74 456
4 12 46 74 456
foreach (var i in data) if(i % 2 == 0) lsSortedEven.Add(i);
이 형태를
var sortedEven = from i in data
where i % 2 == 0
orderby i
select i;
이렇게 사용할 수 있음을 알려준다
이때 where는 조건, orderby는 정렬 기준을 말하며, select는 반환값을 의미한다
즉, 일반 List를 foreach로 하면 Sort()를 추가로 해야하지만, LINQ를 사용하면 값 찾기, 정렬을 동시에 할 수 있다.
121. LINQ를 이용한 조건 검색과 정렬
using System;
using System.Collections.Generic;
using System.Linq;
namespace P121
{
class Program
{
static void Main(string[] args)
{
List<int> data = new List<int>() { 123, 45, 12, 89, 456, 1, 4, 74, 46 };
Print(data);
var IstEven = from v in data where (v > 20 && v % 2 == 0) orderby v descending select v;
Print(IstEven);
var IstSorted = from v in data orderby v ascending select v;
Print(IstSorted);
}
private static void Print(IEnumerable<int> data)
{
foreach (int item in data)
{
Console.Write($"[{item}] ");
}
Console.WriteLine();
}
}
}
결과
[123] [45] [12] [89] [456] [1] [4] [74] [46]
[456] [74] [46]
[1] [4] [12] [45] [46] [74] [89] [123] [456]
LINQ를 사용하여 List<>의 값들을 정리하는 예제를 보여주는 코드이다.
var IstSorted = from v in data orderby v ascending select v;
where없이 정렬만 사용하기도 하는데, 굳이 사용해야 되나 싶다...
핵심은 LINQ값을 반환하면 IEnumeable로 반환된다는 것이다. List가 아니다!
122. LINQ의 결과를 리스트나 배열로 반환
using System;
using System.Collections.Generic;
using System.Linq;
namespace P122
{
class Program
{
static void Main(string[] args)
{
List<int> data = new List<int>() { 123, 45, 12, 89, 456, 1, 4, 74, 46 };
Print(data);
List<int> Odd = new List<int>();
Odd = SelectOddSort(data);
Print(Odd);
Int32[] arrOdd;
arrOdd = SelectOddSort(data).ToArray();
Print(arrOdd);
}
private static List<int> SelectOddSort(List<int> arr)
{
return (from v in arr where v % 2 == 1 orderby v select v).ToList<int>();
}
private static void Print(IEnumerable<int> data)
{
foreach (int item in data)
{
Console.Write($"[{item}] ");
}
Console.WriteLine("\n");
}
}
}
결과
[123] [45] [12] [89] [456] [1] [4] [74] [46]
[1] [45] [89] [123]
[1] [45] [89] [123]
LINQ의 반환을 List<>로 사용해 보는 코드
원래 .ToArray();이게 책에는 없이도 작동이 되는데, 난 안된다...
123. 쿼리의 결과를 새로운 객체 컬렉션으로 저장하는 방법
using System;
using System.Collections.Generic;
using System.Linq;
namespace P123
{
class Student
{
public string Name { get; set; }
public int Id { get; set; }
public List<int> Scores { get; set; }
}
class Program
{
static List<Student> students;
static void Main(string[] args)
{
students = new List<Student>()
{
new Student { Name = "A", Id = 1 , Scores = new List<int>() { 1, 50 } },
new Student { Name = "B", Id = 2 , Scores = new List<int>() {3, 60} },
new Student { Name = "C", Id = 3 , Scores = new List<int>() {5, 70} }
};
Print(students);
High(0, 3);
High(1, 60);
}
private static void High(int n ,int cut)
{
var high = from Student in students where Student.Scores[n] >= cut select new { Name = Student.Name, Scores = Student.Scores[n] };
foreach (var v in high)
{
Console.Write($"[{v.Name}] : {v.Scores}");
}
Console.WriteLine();
}
private static void Print(List<Student> value)
{
foreach (var v in value)
{
Console.Write($"[{v.Name}] [{v.Id}] [{v.Scores[0]} {v.Scores[1]}] " );
}
Console.WriteLine("\n");
}
}
}
결과
[A] [1] [1 50] [B] [2] [3 60] [C] [3] [5 70]
[B] : 3[C] : 5
[B] : 60[C] : 70
LINQ로 만든 결과를 new 객체에 담아서 즉시 출력해보는 코드이다.
이때 Students를 static으로 만들어, 메소드가 매개변수 없이 작동할 수 있게 설계되어 있다.
124. Linq, Group By로 데이터를 분류
using System;
using System.Collections.Generic;
using System.Linq;
namespace P124
{
class Student
{
public string Name { get; set; }
public int Id { get; set; }
public List<int> Scores { get; set; }
}
class Program
{
static List<Student> students;
static void Main(string[] args)
{
students = new List<Student>()
{
new Student { Name = "A", Id = 1 , Scores = new List<int>() { 80, 80 } },
new Student { Name = "B", Id = 2 , Scores = new List<int>() {90, 80} },
new Student { Name = "C", Id = 3 , Scores = new List<int>() {5, 80} },
new Student { Name = "D", Id = 4 , Scores = new List<int>() {5, 90} }
};
var result = from v in students
group v by v.Scores.Average() >= 80 into g
select new
{
key = g.Key? "over 80" : "low 80",
count = g.Count(),
avr = g.Average(v => v.Scores.Average()),
max = g.Max(v => v.Scores.Max())
};
foreach ( var v in result )
{
Console.WriteLine( $"{v.key} 학생수 {v.count}" );
Console.WriteLine($"{v.key} 평균 {v.avr:F2}");
Console.WriteLine($"{v.key} 최고 {v.max:F2}");
Console.WriteLine();
}
}
}
}
결과
over 80 학생수 2
over 80 평균 82.50
over 80 최고 90.00
low 80 학생수 2
low 80 평균 45.00
low 80 최고 90.00
Linq의 결과를 result에 넣어서 2개의 key로 분류하여 출력하는 코드이다.
이때 group by를 사용하게 된다.
'공부 > C#' 카테고리의 다른 글
스크립트에 변수가 많을 시 어떻게 정리할 것인가? - class 사용 정리 아이디어 정리 (0) | 2024.11.26 |
---|---|
C# 공부(11) 101~110 (0) | 2024.08.27 |
C# 공부(10) 93~100 (0) | 2024.08.27 |
C# 공부(10) 91~92(Part2 End) (0) | 2024.08.26 |
C# 공부(9) 81~90 (0) | 2024.08.26 |