lmap — 여러 리스트를 돌며 결과 모으기
lmap — 여러 리스트를 돌며 결과 모으기
리스트의 모든 원소를 하나씩 처리하면서, 각 반복에서 나온 결과를 다시 리스트로 모으고 싶을 때가 있어요. 이런 때 쓰는 명령어가 lmap이에요. foreach가 반복만 할 뿐 결과를 모으지 않는 것과 달리, lmap은 본문이 실행될 때마다 그 결과를 누적해 하나의 리스트로 돌려줘요. 리스트를 여러 개 짝지어(zip) 돌릴 수도 있어요.
출처: 문서
본문
lmap 명령어는 한 개 이상의 리스트에서 루프 변수가 값을 받아가며 루프를 실행하고, 각 반복에서 모은 결과의 리스트를 돌려주는 루프예요.
가장 단순한 경우에는 루프 변수 varname 하나와 값 리스트 list 하나가 있어요. body 인수는 Tcl 스크립트예요. list의 각 원소에 대해(처음부터 끝까지 순서대로) lmap은 lindex 명령어로 원소를 꺼낸 것처럼 그 내용을 varname에 할당한 다음, Tcl 인터프리터를 호출해 body를 실행해요. body의 실행이 정상적으로 끝나면 그 결과가 누적 리스트에 추가돼요. lmap은 그 누적 리스트를 반환해요.
일반적인 경우에는 값 리스트가 둘 이상(예: list1와 list2) 있을 수 있고, 각 값 리스트는 루프 변수 리스트(예: varlist1와 varlist2)와 연결돼요. 루프가 반복될 때마다 각 varlist의 변수들에는 해당 리스트에서 연속된 값이 할당돼요. 각 리스트의 값은 처음부터 끝까지 순서대로 쓰이고, 각 값은 정확히 한 번만 쓰여요. 전체 루프 반복 횟수는 모든 값 리스트의 값을 다 소진할 만큼 커요. 어떤 값 리스트에 각 반복을 위한 변수만큼 원소가 충분하지 않으면, 빠진 원소에는 빈 값이 쓰여요.
body 안에서 break와 continue 문을 호출할 수 있는데, for와 foreach 명령어에서와 같은 효과를 가져요. 이 경우에는 body가 정상적으로 끝나지 않으므로 결과가 누적 리스트에 추가되지 않아요.
구문은 다음과 같아요.
lmap varname list body
lmap varlist1 list1 ?varlist2 list2 ...? body
예시
리스트를 짝지어(zip) 묶기:
set list1 {a b c d}
set list2 {1 2 3 4}
set zipped [lmap a $list1 b $list2 {list $a $b}]
# The value of zipped is "{a 1} {b 2} {c 3} {d 4}"
홀수 값을 제거하도록 리스트를 걸러내기:
set values {1 2 3 4 5 6 7 8}
proc isEven {n} {expr {($n % 2) == 0}}
set goodOnes [lmap x $values {expr {
[isEven $x] ? $x : [continue]
}}]
# The value of goodOnes is "2 4 6 8"
리스트 내용을 기준으로 앞부분(prefix)을 잘라내기:
set values {8 7 6 5 4 3 2 1}
proc isGood {counter} {expr {$n > 3}}
set prefix [lmap x $values {expr {
[isGood $x] ? $x : [break]
}}]
# The value of prefix is "8 7 6 5 4"
더 알아보기
break,continue,for,foreach,while