데이터와 제어

컬렉션과 컴프리헨션

순서·키 조회·중복 처리에 맞춰 Array, Map, Set을 고르고 값을 걸러 새 컬렉션을 만드는 방법을 설명합니다.

순서대로 값을 보관하려면 Array, 키로 조회하려면 Map, 중복을 없애려면 Set을 고르세요. 컴프리헨션으로 값을 걸러 변환하고 새 컬렉션을 만들 수 있습니다.

첫 프로그램을 따라 토파즈를 설치하세요. 배열과 반복문은 데이터와 제어에서 먼저 익힐 수 있습니다.

점수를 거르고 없는 위치 조회하기

작업 폴더에 다음 코드를 collections-comprehensions.tpz로 저장하세요.

TOPAZ
let 점수들 = [10, 25, 10]
let 레이블들 = map { "Ada": 10, "Lin": 25 }
let 고유값들 = set { 10, 25, 10 }
let 집중값들 = [ for 점수 in 점수들 if 점수 >= 20 => 점수 * 2 ]

let 첫값 = 점수들[0]
let 누락 = 점수들.get(9)
let 에이다포함 = "Ada" in 레이블들.keys
let 누락표시 = match 누락 {
    case Some(값) => "found {값}"
    case None => "missing"
}

print("{점수들}:{고유값들.toArray()}:{레이블들.keys}")
print("{집중값들}:{첫값}:{에이다포함}")
print(누락표시)

같은 폴더에서 파일을 검사하고 실행하세요.

BASH
topaz check collections-comprehensions.tpz
topaz run collections-comprehensions.tpz

검사는 종료 코드 0으로 성공합니다. 실행하면 다음 결과를 출력합니다.

출력
[10, 25, 10]:[10, 25]:[Ada, Lin]
[50]:10:true
missing

입력에서 결과까지 따라가기

배열은 [10, 25, 10]을 유지합니다. 집합은 처음 넣은 순서대로 [10, 25]를 남깁니다. 맵은 "Ada"에 10, "Lin"에 25를 연결합니다. keys 배열도 이 삽입 순서를 유지합니다.

집중값들에 넣는 식이 컴프리헨션입니다. 각 점수를 읽고 20 이상인 값을 골라 두 배로 만듭니다. 이 입력에서는 25가 조건을 통과해 50이 되므로 결과는 [50]입니다.

필요한 작업선택순서와 중복
위치로 값 읽기Array<T>인덱스가 증가하는 순서, 중복 유지
키로 값 읽기Map<K, V>키를 삽입한 순서
서로 다른 값 보관하기Set<T>각 값을 처음 삽입한 순서

컬렉션 읽기와 변경

점수들[0]은 10을 읽습니다. 직접 인덱스로 읽을 때 음수나 범위 밖 인덱스를 쓰면 실행 오류가 납니다. 해당 위치가 없을 수 있다면 점수들.get(9)를 쓰세요. 이 호출은 None을 반환하므로 예제는 missing을 출력합니다. 값이 있으면 get은 Some(값)을 반환합니다. 이 두 경우를 표현하는 타입이 Option입니다.

컬렉션 자체를 바꾸려면 push 같은 변경 메서드를 부르기 전에 뿌리 바인딩을 let mut로 선언하세요. 변경할 수 없는 바인딩도 새 컬렉션을 만드는 식의 입력으로 쓸 수 있습니다.

맵을 만들 때는 키를 중복해서 쓸 수 없습니다. 같은 리터럴 키를 반복하면 정적 오류가 납니다. 실행 중 키가 같아지면 원본의 모든 피연산자를 성공적으로 계산한 뒤 실행 오류가 납니다. 키 추가나 값 변경이 목적이면 insert를 쓰세요.

기존 맵의 값을 바꿔도 키 순서는 유지됩니다. 맵 항목이나 집합 요소를 삭제하면 해당 위치도 사라집니다. 다시 넣으면 맨 뒤에 붙습니다.

리터럴·반복문·컴프리헨션 고르기

  • 항목을 직접 적으려면 [a, b], set { a, b }, map { key: value }를 쓰세요.
  • 여러 단계를 수행하려면 for item in source { ... }를 쓰세요. 문장으로 쓰면 출력 같은 동작을 수행합니다. 식으로 쓰면 본문 결과를 Array에 모읍니다.
  • 필터링과 변환에는 [ for item in source if condition => result ]를 쓰세요. 집합은 set { for item in source => result }, 맵은 map { for item in source => key: value }로 만듭니다.

컴프리헨션은 for로 시작합니다. 추가 for나 if 절은 쉼표 없이 연결하고 => 뒤에 결과를 적으세요. 각 절은 왼쪽부터 차례로 중첩됩니다. 실행한 모든 절과 본문 계산이 성공하면 결과 컬렉션을 사용할 수 있습니다.

조회와 리터럴 고치기

맵의 키를 찾으려면 "Ada" in 레이블들.keys를 쓰세요. "Ada" in 레이블들은 쓸 수 없습니다.

배열 타입에는 [T] 대신 Array<T>를 쓰세요. 집합은 set, 맵은 map으로 시작합니다. { key: value }는 구조적 레코드를 만듭니다. 맵을 만들지는 않습니다. #{...}는 잘못된 문법입니다.

collections-comprehensions.tpz의 점수들.get(9)를 점수들[9]로 바꾸면 인덱스 범위 오류로 실행이 멈춥니다. 값이 없을 수 있다면 get을 유지하세요. 직접 읽으려면 인덱스를 먼저 고치세요.

컴프리헨션의 패턴은 도달한 각 항목과 일치해야 합니다. 일치하지 않으면 실행 오류가 납니다. 뒤의 패턴으로 값을 꺼내기 전에 if 절로 원하지 않는 항목을 거르세요.

다른 컬렉션 규칙

  • 배열 스프레드는 다른 Array를 받습니다. 집합·맵 리터럴과 컴프리헨션에는 스프레드 문법이 없습니다.
  • 빈 set {}과 map {}에는 기대 타입 Set<T>나 Map<K, V>가 필요합니다.
  • 맵 키와 집합 요소는 키 비교를 지원해야 합니다. 복합 값은 내부 구성 요소도 모두 이를 지원해야 합니다. 이 성질을 키 사용 가능성이라고 합니다.
  • for는 배열·정수 범위·집합·map.keys를 정해진 순서로 읽습니다. 문자열은 스칼라 연산으로 유니코드 스칼라 값을 꺼내세요.
  • 사용자 정의 순회·제너레이터·지연 또는 병렬 컴프리헨션·임의 순회 값의 스프레드·순서 없는 컬렉션은 지원하지 않습니다.

순회 중 값에 이름을 붙이는 방법은 패턴과 제어 흐름을 참고하세요. 사용할 수 있는 메서드는 컬렉션 연산에 있습니다.