4주차 강의 중에 배열의 원소를 무작위 순서로 정렬하는 구현 과정이 있었는데, 내가 생각했던 것과 다르게 간단하게 코드 한 줄로 구현할 수 있었다.
정렬할 배열을 arr
라 치자. 길이가 같은 arr2
배열과 visited
배열을 선언해둔다. arr
의 첫번째 원소부터 반복문을 돌면서 arr2
배열의 무작위 인덱스에 넣고 visited
배열에 해당 인덱스에는 값이 들어왔다고 기록한다. 만약 이미 값이 들어 있는 인덱스 (visited[i] == true
)라면 무작위 인덱스를 다시 뽑는다.
int[] rtans = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
int[] arr2 = new int[rtans.Length];
bool[] visited = new bool[rtans.Length];
for (int i = 0; i < rtans.Length; i++)
{
while (true)
{
int randomIndex = Random.Range(0, arr2.Length);
if (!visited[randomIndex])
{
arr2[randomIndex] = rtans[i];
visited[randomIndex] = true;
break;
}
}
}
rtans = arr2;
길다.. 그리고 while (true)
라니 무섭다.. 만약 배열의 길이가 수억개로 아주 길었다면, 마지막 원소를 정렬할 때 (1/수억) 확률을 뚫어야 정렬이 완료된다. 만약에 강의에서 나온 방법이 아니라 이런식으로 구현하려 했다면 인덱스 번호
를 key, -1 ~ 1 사이의 랜덤한 실수값
을 value로 갖는 pair를 만들어서 value를 기준으로 정렬하는 heap
에 넣어 heap sort를 하는게 더 빠르지 않았을까 싶다.
int[] rtans = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
rtans = rtans.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();
Linq
의 기능인 OrderBy
를 이용해서 간단하게 한줄로 구현할 수 있었다.
그렇다면 Linq
는 무엇인가? 그리고 item => Random.Range(-1.0f, 1.0f)
는 뭘 의미하길래 랜덤으로 정렬이 되는걸까? 일단 =>
는 람다(lambda)라고 한다. Linq
와 lambda식
에 대해 알아보자.
Linq
는 c# 3.0에서 생긴 기능이라고 한다. 간단하게 말하면 언어에 통합된 쿼리
이다. 배열에다 SQL을 이용해 값을 찾거나, 정렬할 수도 있다. 다음은 Linq
의 대표적인 SQL 연산자이다.
Where : 질의 조건에 맞는 데이터를 추출하는데 사용합니다.
Select : 질의 결과를 원하는 형식으로 변환할 때 사용합니다.
OrderBy : 질의 결과를 원하는 순서대로 정렬할 때 사용합니다.
GroupBy : 질의 결과를 특정 조건 기준으로 묶을 때 사용합니다.
Join : 두개의 질의 결과를 연결하여 하나의 질의 결과로 만들 때 사용합니다.
여기에서 Linq
에 대해 다 정리하면 글이 너무 길어질 것 같으니 우리가 궁금한 OrderBy
부분을 알아보자.
lambda
역시 c# 3.0에서 생긴 기능이라고 한다. c#에서 lambda
는 c#의 delegate
키워드에서 발전된 형태라고 생각하면 된다. delegate
는 또 뭔데? 라고 한다면 우리말로는 대리자
라고도 하며, c++의 함수포인터와 비슷한 역할을 한다. 파라미터와 리턴값의 type이 같은 메서드를 가리킬 수 있는데, 이를 이용하여 event나 callback을 만들 수 있다.
lambda
는 간결하고 간편한 문법을 사용하여 개발자가 작성한 코드를 더 간결하고 가독성 있게 만들어 주는 기능이라고 한다. 람다식을 통해 인자를 넘길 수 있으며 기존에 사용한 delegate
나 익명 메서드를 대신하여 간단한 작성과 코드 이해도를 높일 수 있댄다..
lambda
는 delegate
대신 =>
(람다연산자)를 사용한다. 예를 들어 ..
다음의 경우
var list = students.OrderBy(x => x.score).ToList();
에서의 람다식 x => x.score
를 해석해보자면, students
배열의 임의의 요소 x
를 x.score
를 우선순위로 정렬한다. 쯤으로 이해하면 될 것 같다.
오늘 강의에서 나온
rtans = rtans.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();
에서의 람다식 item => Random.Range(-1.0f, 1.0f)
를 해석해보자면, rtans
배열의 임의의 요소 item
을 -1 ~ 1 사이의 랜덤한 실수의 우선순위
로 정렬한다. 쯤으로 이해하면 될 것 같다. item
마다 우선순위가 다르니 결과적으로 배열 안의 원소들은 무작위 순서로 정렬될 것이다.
delegate
와 lambda
의 차이를 자세하게 설명한 글이 있다. 두고 두고 읽어보면 좋을 것 같다.
람다식은 아직 많이 생소하다. 간결함과 가독성을 위해 만들어졌다는데 아직 한 눈에 안들어오는 것을 보니깐 앞으로 많이 써봐야겠다. c++의 sort()
함수처럼 OrderBy
역시 사용자가 직접 만든 compare()
함수를 이용하여 입맛대로 정렬할 수도 있다는데, 정렬은 정말 자주 쓰고 중요한 기능이니까 까먹지 말아야겠다.
https://centbin.com/%EB%9E%8C%EB%8B%A4%EC%8B%9D%EA%B3%BC-linq-%EA%B8%B0%EC%B4%88/
https://koco-pot.co.kr/c-%EC%96%B8%EC%96%B4%EC%97%90%EC%84%9C%EC%9D%98-linq%EC%99%80-%EB%9E%8C%EB%8B%A4%EC%8B%9D-%ED%99%9C%EC%9A%A9-%EB%B0%A9%EB%B2%95/
https://learn.microsoft.com/ko-kr/dotnet/api/system.linq.enumerable.orderby?view=net-7.0
와 글 정말 잘쓰신 것같습니다!