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 enumEnum.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/2
  • take/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 모듈을 참고하세요.