컬렉션 및 목록
특정 형식의 데이터가 둘 이상 있는 경우가 있을 텐데요. 이때 각 데이터에 대해 변수를 만들 수도 있고, 데이터를 모두 하나의 컬렉션으로 그룹화할 수도 있습니다. 데이터를 그룹화하면 개별 데이터가 아닌 컬렉션 전체에 메서드를 적용하는 등과 같은 이점을 얻을 수 있습니다.
컬렉션
컬렉션을 사용해야 한다는 것을 알 수 있는 첫 번째 신호는 같은 데이터 형식을 갖는 것으로 보이는 데이터가 여러 개 있는 경우입니다. 다음 코드와 같이 항목이 여러 개 있는 시나리오가 있을 수 있습니다.
let logEntryMonday = "first entry"
let logEntryTuesDay = "second entry"
let logEntryWednesday = "third entry"
위 코드에서, 비슷한 항목들을 하나씩 계속해서 추가할 수도 있겠지만, 어느 시점이 되면 이 방법이 실용적이지 않게 느껴지게 됩니다. 개별 항목들은 서로 관련이 있을 뿐 아니라 동일한 형식을 갖는데, 그렇다면 각 항목에 대해 하나씩 새 변수를 만드는 것이 좋은 생각일까요? 그렇지 않을 가능성이 있습니다. 그 대신 데이터 추가 또는 제거하기나 그 밖의 연산을 사용하는 등 논리적이고 관리가 편리한 그룹화를 사용할 수 있는 컬렉션을 사용하는 것이 좋습니다.
logEntriesWeek = ["first entry"; "second entry"; "third entry"]
위 코드는 입력해야 할 텍스트가 많지 않을 뿐만 아니라 관련 있는 모든 데이터가 하나로 질서 있게 그룹화됩니다.
그렇다면 F#에는 어떤 기능이 있을까요? F#은 각각 특정 상황에서 사용하도록 설계된 세 가지 형식의 컬렉션을 제공합니다.
목록: F#의 목록은 동일한 형식을 갖는 요소들의 ‘변경 불가’하며 순서가 지정된 집합입니다. 변경 불가란 목록은 배열보다 더 나은 성능을 제공할 수 있지만 콘텐츠를 변경하려는 경우 배열을 사용할 때보다 더 복잡할 수 있음을 의미합니다. 예를 들어, 기존 목록에서 새 목록을 만들 수 있습니다. 이 단원에서는 목록을 사용하는 방법을 설명합니다.
배열: 배열은 0부터 시작하는 인덱스로 연속적으로 정렬되는 동일한 형식의 데이터 요소로 구성된 고정 크기의 변경 가능한 컬렉션입니다. 변경 가능이란 데이터 요소를 쉽게 추가하고 제거할 수 있다는 의미인데, 성능 저하가 있을 수 있습니다.
시퀀스: 시퀀스는 동일한 형식을 갖는 요소의 논리 계열입니다. 시퀀스는 요소를 모두 다 사용하지 않을 것으로 예상되는 경우에 대량의 데이터 컬렉션에 적합하기 때문에 Just-In-Time 특징을 갖습니다. 시퀀스는 또한 필요한 경우에만 요소를 계산합니다. 따라서 시퀀스는 특정 상황에서 목록보다 더 나은 성능을 제공할 수 있습니다.
목록
앞에서 설명했듯이 요소들의 목록은 변경 불가하며 순서가 지정된 집합입니다. 아래에서 목록을 만드는 몇 가지 방법을 살펴보세요.
let cards = ["Ace"; "King"; "Queen"]
이 코드에서는 요소를 대괄호([]
)로 묶어서 목록을 정의합니다. 목록의 각 항목은 세미콜론(;
)으로 구분됩니다.
목록을 만드는 또 다른 방법은 아래 코드에서처럼 각 요소를 새 줄에 입력하는 것입니다. 이렇게 하면 세미콜론을 사용할 필요가 없습니다.
let cards = [
"Ace"
"King"
"Queen"
]
목록에 포함된 요소는 형식이 동일해야 하므로 다음과 같은 선언은 허용되지 않습니다.
let cards = [ 1; "Ace"; "King" ] // not permitted
위 코드는 선언에 숫자와 문자열이 섞여 있으므로 허용되지 않습니다. 목록을 만드는 또 다른 방법은 범위 연산자(..
)를 사용하는 것입니다. 시작 요소와 종료 요소를 범위 연산자(..
)로 구분하여 지정하면 됩니다. 이렇게 하면 시작 요소부터 종료 요소까지의 모든 숫자가 만들어집니다. 예를 들어, 아래 코드를 사용하여 숫자 1 2 3 4 5
를 만들 수 있습니다.
let numbers = [ 1 .. 5 ]
목록 변경하기
앞에서 설명했듯이 목록은 변경 불가합니다. 즉, 목록은 변경할 수 없습니다. 하지만 다르게 생각해 보면 목록에 하나의 항목을 추가하거나 항목으로 이루어진 목록을 추가하는 것처럼 만들 수 있습니다. 어떤 의미인가요? 다음 예제를 참조하세요.
let cards = ["Ace"; "King"; "Queen"]
위 코드는 세 개의 문자열로 구성된 목록입니다. 이중 콜론(::
) 연산자를 사용하면 목록 맨 처음에 항목을 추가할 수 있습니다. 그러면 새 목록이 만들어지고, 기존 목록은 영향을 받지 않습니다.
let cards = ["Ace"; "King"; "Queen"]
let newList = "Jack" :: cards // "Jack", "Ace", "King", "Queen"
아래와 같이 @
연산자를 사용하여 목록을 추가할 수도 있습니다.
let cards = ["Ace"; "King"; "Queen"]
let otherCardList = ["Jack"; "10"]
let fullList = cards @ otherCardList // "Ace", "King", "Queen", "Jack", "10"
목록 모듈에는 append()
함수가 있는데, 이 함수는 배열 컬렉션과 시퀀스 컬렉션에서 사용할 수 있습니다. append()
는 컬렉션 형식을 목록에서 시퀀스로 변경해야 하거나 항목을 추가하는 새로운 방법을 익히고 싶지 않을 때 사용하기 좋습니다. @
기호를 사용하여 목록에 요소를 추가하는 방법은 목록 구조에서만 사용할 수 있습니다. 두 예제를 다시 살펴보고 대신 append()
를 사용합니다.
let cards = ["Ace"; "King"; "Queen"]
let otherCardList = ["10"; "9"]
let fullList = cards |> List.append ["Jack"] // "Jack", "Ace", "King", "Queen"
let fullList = cards |> List.append otherCardList // "10", "9", "Ace", "King", "Queen"
속성
F#의 목록은 연결된 목록으로 구현됩니다. 즉, 목록은 요소가 다른 요소에 연결된 구조입니다. 그 밖에도 알아 두어야 하는 용어로 목록의 첫 번째 요소인 헤드와 헤드를 제외한 요소를 포함하는 테일이 있습니다. 예를 들어, 목록 1 2 3 4
에서 헤드는 1
이고 테일은 2 3 4
입니다.
이 방식으로 요소를 구분하면 첫 번째 요소에 빠르게 액세스하여 읽어 들이거나, 제거하거나, 그 밖의 동작을 수행할 수 있습니다. 목록에 있는 특정 항목에 액세스하려면 0부터 시작하는 인덱스를 받는 Item
속성을 사용할 수 있습니다. 아래의 코드를 살펴보세요.
let list = [1; 2; 3; 4]
list.Item 1 // 2
다음 표에는 목록 속성이 나와 있습니다.
속성 | 설명 |
---|---|
Head | 목록의 첫 번째 요소 |
Empty | 빈 목록을 반환합니다. 빈 목록을 만들 때 사용할 수 있습니다. |
IsEmpty | 현재 목록이 비어 있는지 확인합니다. |
항목 | 지정된 위치(0부터 시작하는 인덱스)에 있는 현재 요소 검색 |
길이 | 목록의 항목 수 반환 |
Tail | 목록의 첫 번째 요소를 제외한 모든 요소를 반환합니다. |