Enum 치트시트 — 컬렉션 작업 함수 빠른 참조
Enum 치트시트 — 컬렉션 작업 함수 빠른 참조
Enum 모듈, 즉 컬렉션(이를 enumerable이라 불러요)을 다루는 모듈의 빠른 참조예요. 아래 예시들은 대부분 다음 데이터 구조를 사용해요.
cart = [
%{fruit: "apple", count: 3},
%{fruit: "banana", count: 1},
%{fruit: "orange", count: 6}
]
일부 예시는 =~ 연산자를 쓰는데, 이 연산자는 왼쪽 문자열이 오른쪽 문자열을 포함하는지 검사해요.
출처: Enum cheatsheet
본문
판별(Predicates)
any?/2— 적어도 하나가 참이면true. 빈 컬렉션이면 항상false.
iex> Enum.any?(cart, & &1.fruit == "orange")
true
iex> Enum.any?([], & &1.fruit == "orange")
false
all?/2— 모두 참이어야true. 빈 컬렉션이면 항상true.member?/2— 값이 존재하는지 검사.item in enum은Enum.member?(enum, item)과 동일해요.empty?/1— 비어있는지 검사.
필터링
filter/2— 함수가 참인 요소만 반환.reject/2— 함수가 참인 요소를 제외.flat_map/2— 변환과 필터를 한 번에 해요. 결과에서 제외할 항목은 빈 리스트를 반환하면 돼요.
iex> Enum.filter(cart, &(&1.fruit =~ "o"))
[%{fruit: "orange", count: 6}]
iex> Enum.flat_map(cart, fn item ->
...> if item.count > 1, do: [item.fruit], else: []
...> end)
["apple", "orange"]
필터링은 comprehension으로도 할 수 있어요. comprehension 안의 패턴 매칭도 필터처럼 동작해요.
iex> for %{count: 1, fruit: fruit} <- cart do
...> fruit
...> end
["banana"]
매핑
map/2— 각 요소에 함수를 적용해 결과 리스트 반환.map_every/3— n번째 요소마다 적용.
iex> Enum.map(cart, & &1.fruit)
["apple", "banana", "orange"]
comprehension으로도 매핑할 수 있고, 필터와 매핑을 동시에 할 수도 있어요.
iex> for item <- cart, item.fruit =~ "e" do
...> item.fruit
...> end
["apple", "orange"]
부수 효과(Side-effects)
each/2— 부수 효과 전용으로 써요. 각 요소에 함수를 호출하고:ok를 반환.
iex> Enum.each(cart, &IO.puts(&1.fruit))
apple
banana
orange
:ok
누산(Accumulating)
reduce/3— 누산기(acc)를 이어가며 하나의 값으로 줄여요.map_reduce/3— 매핑과 축약을 함께.scan/3— 매 단계의 누산 결과 리스트를 반환.reduce_while/3—{:halt, term}을 반환할 때까지 축약.
iex> Enum.reduce(cart, 0, fn item, acc ->
...> item.count + acc
...> end)
10
iex> Enum.scan(cart, 0, fn item, acc ->
...> item.count + acc
...> end)
[3, 4, 10]
comprehension으로도 축약(reduce: 0)할 수 있고, 필터와 축약을 함께 할 수도 있어요.
집계(Aggregations)
count/1,count/2— 개수(함수 조건 포함 가능).count_until로 상한까지 세기도 해요.frequencies/1,frequencies_by/2— 요소 빈도 맵.sum/1,sum_by/2— 합. 한 번에 처리하려면sum_by/2를 쓰는 게 좋아요.product/1,product_by/2— 곱.
iex> Enum.sum_by(cart, & &1.count)
10
iex> Enum.frequencies(["apple", "banana", "orange", "apple"])
%{"apple" => 2, "banana" => 1, "orange" => 1}
정렬(Sorting)
sort/1,sort_by/3— 정렬. 구조체를 정렬할 때는 모듈을 sorter로 써요.min/2,max/2,min_by/3,max_by/3— 최소·최대.
iex> Enum.sort_by(cart, & &1.count)
[%{fruit: "banana", count: 1}, %{fruit: "apple", count: 3}, %{fruit: "orange", count: 6}]
iex> Enum.max_by(cart, & &1.count)
%{fruit: "orange", count: 6}
연결·펼치기
concat/1,concat/2— 여러 enumerable을 하나의 리스트로.flat_map/2,flat_map_reduce/3— 매핑 후 한 겹만 펼침.
comprehension으로도 펼칠 수 있어요. for item <- cart, fruit <- List.duplicate(...) 처럼 생성기를 여러 번 반복하면 돼요.
변환(Conversion)
into/2,into/3— enumerable을 collectable에 넣음.to_list/1— 리스트로 변환.
iex> Enum.into(cart, %{}, fn item -> {item.fruit, item.count} end)
%{"apple" => 3, "banana" => 1, "orange" => 6}
comprehension의 into: 옵션으로도 가능해요.
중복·유일(Duplicates & uniques)
dedup/1,dedup_by/2— 연속된 중복만 제거.uniq/1,uniq_by/2— 컬렉션 전체 기준 중복 제거. comprehension의uniq: true옵션도 지원돼요.
인덱싱(Indexing)
at/3— 인덱스 요소를 반환(없으면default). 루프 안에서 인덱스로 리스트에 접근하는 건 권장하지 않아요.fetch/2—{:ok, elem}또는:error.fetch!/2— 없으면Enum.OutOfBoundsError를 던짐.with_index/1,with_index/2— 인덱스를 붙임.
찾기(Finding)
find/3— 조건을 만족하는 첫 요소(없으면 default).find_index/2— 조건을 만족하는 첫 요소의 인덱스.find_value/3— 첫 참 값.
그룹화(Grouping)
group_by/3— 키 함수와 (선택) 값 함수로 그룹화.
iex> Enum.group_by(cart, &String.last(&1.fruit), & &1.fruit)
%{"a" => ["banana"], "e" => ["apple", "orange"]}
연결·사이사이(Joining & interspersing)
join/2,map_join/3— 구분자로 문자열 결합.intersperse/2,map_intersperse/3— 요소 사이에 구분자를 끼움.
자르기(Slicing)
slice/2,slice/3— 범위나 시작 인덱스·개수로 자름. 음수 범위는 뒤에서부터 세요.slide/3— 요소(또는 범위)를 다른 위치로 이동.
뒤집기(Reversing)
reverse/1,reverse/2— 뒤집음.reverse/2의 tail은 결과의 꼬리로 붙어요.reverse_slice/3— 일부 구간만 뒤집음.
나누기(Splitting)
split/2— 개수 기준으로 두 리스트로 나눔(음수는 뒤에서부터).split_while/2— false가 나오는 즉시 멈춤.split_with/2— 컬렉션 전체를 기준으로 나눔.
자르기(drop & take)
drop/2,drop_every/2,drop_while/2take/2,take_every/2,take_while/2
음수 개수는 뒤에서부터 세요.
무작위(Random)
random/1,take_random/2,shuffle/1— 호출마다 결과가 달라져요.
묶기(Chunking)
chunk_by/2— 함수가 새 값을 반환하는 지점마다 분리.chunk_every/3,chunk_every/4— count·step·leftover로 묶음. 커스텀 묶기는chunk_while/4를 봐요.
병합(Zipping)
zip/2,zip_with/3,zip_reduce/4,unzip/1— 여러 컬렉션을 짝지어 처리.
iex> Enum.zip(fruits, counts)
[{"apple", 3}, {"banana", 1}, {"orange", 6}]
많은 컬렉션을 한 번에 병합하려면 zip/1, zip_with/2, zip_reduce/3을 참고하세요.
더 알아보기
Enum모듈 문서에서 각 함수의 전체 시그니처와 상세 예시를 볼 수 있어요.- 느긋한(lazy) 처리가 필요하면
Stream모듈을 참고하세요.