본문 바로가기
개발 공부 기록하기/- Kotlin & Java

Kotlin 리스트 분할 및 병합하기(with chunked, windowed)

by soulduse 2020. 9. 2.
반응형

 

아래와 같은 리스트 2개가 있고, 두 개 리스트를 합쳐서 아래와 같은 결과를 만들고 싶다면 어떻게 해야 될까?

A List

1 2 3 4 5 6 7 8 9

B List

100 200 300 400 500 600 700 800 900


결과 List

100 200 300 1 2 3 400 500 600
4 5 6 700 800 900 7 8 9

 

난 아래와 같은 방법을 생각했다. (혹시 더 좋은 알고리즘이나 생각이 있다면 알려주세요)

1. A List와 B List를 각각 3등분으로 나눈다

2. B List를 for문을 돌면서 각 index에 맞춰서 넣어주는 작업을 한다.

3. 합쳐진 list들을 풀어서 평평하게 만드는 만드는 작업을 한다.

코드로 옮겨보면 아래와 같이 된다.

 

하나씩 살펴보자

 1 Line 

val aList = (1..9).chunked(3).toMutableList()

- 1~9까지 가지는 list를 만들기 위해 (1..9)를 사용

- List를 3등분으로 분할 하기위해 chunked(3)를 사용

- 해당 List를 변경 가능하도록 하기위해 toMutableList()로 해주었다.

chunked를 잘 몰라서 어떻게 동작하는지 궁금해서 내부를 보았더니 아래와 같이 되어있었다.

오잉 windowed는 또 뭐야?

내부적으로 size를 windowed로 넘기고 있는게 아닌가? windowed를 다시 열어보면 아래와 같다.

chucked에서 받은 size를 windowed에 size, step을 동일하게 넘겼던 것을 알 수 있다. 그럼 현재는 작은 단위의 리스트라서 내가 원했던 3등분이 정확하게 되었지만, 리스트 값이 커지면 생각한대로 동작하지 않음을 알 수 있었다.

 

역시나 테스트를 돌려보니 실패

 

테스트를 돌려본 결과 3의 결과를 기대 했지만 무려 34개의 리스트로 잘게 쪼개졌다. chucked의 경우 List를 3개의 큰 덩어리로 만들어주는게 아닌, 작은 3개의 청크 단위로 만들어주는 것임을 알 수 있다.

 

그렇다면 내가 원하는 List를 3개의 큰 덩어리로 만드려면 windowed에 List Size를 3으로 나눈 값을 넣어주면 될 것 같았다.

위와 같이 테스트 해보니 잘 통과하는 것을 알 수 있었다. 혹시나 하는 마음에 테스트를 하나 더 추가 해보았는데 실패하는 것이 아닌가?

마지막값이 100이라고 예상했는데, 98이 찍혀있었다. 나눠지고 남은 값들은 버려버린 것이다.

다시 chucked를 살펴보니 partialWindows 이라는 복병이 숨어 있었다.

return windowed(size, size, partialWindows = true)

windowed 함수에 partialWindows는 기본적으로 false인 것을 알 수 있었고, 함수 내부에 사용 되는 곳을 살펴보니

windowed 내부에서 List를 만들어줄때 partialWindows 값에 따라 나머지 값들을 버릴껀지 추가할껀지 조건이 걸려 있었다.

 

결론 적으로 List를 내가 원하는 등분으로 나누려면 두가지 방법중 원하는 것을 사용하면 되는 것을 알 수 있었다.

1. chucked에 List 사이즈를 나눈 값만 넣는 방법

testList.chunked(divideSize)

2. windowed에 List 사이즈를 나눈 값을 size, step, partialWindows를 넣어서 사용하는 방법

testList.windowed(divideSize, divideSize, true)

chucked, windowed를 사용할때는 잘 알고 사용하도록 하자 ㅎㅎ

 

 2 Line 

val bList = (100..900 step 100).chunked(3)

aList와 마찬가지로 3개의 청크 단위로 나누었다.

 

 3 ~ 5 Line 

bList.forEachIndexed { index, list ->
    aList.add(index * 2, list)
}

List<List<Int>

[[100, 200, 300], [400, 500, 600], [700, 800, 900]] 

리스트 안에 리스트 들이 loop를 돌면서 총 3번 aList에 추가 될 것이다. aList의 Index는 index x 2를 했으니

(0 x 2 = 0 / 1 x 2 = 2 / 2 x 2 = 4) aList의 각각 index에 [100, 200, 300]과 같은 List 덩어리가 추가 될 것이다.

이 과정이 끝나면 아래와 같이 만들어진다.

 6 Line 

val resultList = aList.flatten()

List<List<Int> => List<Int>로 flatten은 말그대로 평평하게 만드는 작업을 한다.

함수 안을 보면 생각보다 단순하다. 빈 어레이를 하나 생성하고 내용물을 하나씩 꺼내서 순서대로 차곡차곡 담는다.

그럼 내가 원했던 아래와 같은 결과물이 나오는 것을 확인 할 수 있다!

 

 

반응형