Set

Set

Set 클래스는 중복이 없는 무순서 값들의 컬렉션을 구현한 라이브러리예요. Array의 직관적인 상호 연산 기능과 Hash의 빠른 조회를 섞어 놓은 느낌이지요.

출처: Ruby 3.3 API

본문

Enumerable에는 편의를 위해 to_set 메서드가 추가돼 있어요. SetEnumerable 객체(each 구현)와 함께 쓰기 쉬워요. 대부분의 초기화 메서드와 이항 연산자는 set·array 외에도 일반 Enumerable 객체를 받아들여요.

Set은 저장소로 Hash를 써요. 그래서 다음 점을 유의해야 해요.

  • 요소의 동등성은 Object#eql?Object#hash에 따라 결정돼요. Set#compare_by_identity를 쓰면 요소를 아이덴티티(identity)로 비교하게 만들 수 있어요.
  • Set은 저장되는 동안 각 요소의 아이덴티티가 바뀌지 않는다고 가정해요. 요소를 수정하면 set이 불안정한 상태가 될 수 있어요.
  • 문자열을 저장할 때, 원래 문자열이 이미 frozen이 아니면 문자열의 frozen 복사본이 대신 저장돼요.

비교 (Comparison)

비교 연산자 <, >, <=, >={proper_,}{subset?,superset?} 메서드의 축약형으로 구현돼 있어요. <=> 연산자는 이 순서를 반영하며, 서로 고유 요소가 다른 set({x, y} vs {x, z})에서는 nil을 돌려줘요.

예제

require 'set'
s1 = Set[1, 2]                        #=> #<Set: {1, 2}>
s2 = [1, 2].to_set                    #=> #<Set: {1, 2}>
s1 == s2                              #=> true
s1.add("foo")                         #=> #<Set: {1, 2, "foo"}>
s1.merge([2, 6])                      #=> #<Set: {1, 2, "foo", 6}>
s1.subset?(s2)                        #=> false
s2.subset?(s1)                        #=> true

여기에 있는 것 (What's Here)

SetObject에서 상속받고 Enumerable(수십 개의 추가 메서드 제공)을 포함해요. 특히 Set은 가져오기(fetch)·반복(iterate) 전용 메서드가 많지 않고 Enumerable에 의존해요. 클래스 Set은 다음에 유용한 메서드를 제공해요.

  • 생성: ::[] — 주어진 객체들을 담은 새 set을 돌려줘요. ::new — 주어진 객체들(블록 없음)이나 블록 반환값들(블록 있음)을 담은 새 set을 돌려줘요.
  • 집합 연산: | (union, +) — self와 주어진 enumerable의 모든 요소(중복 없음)를 담은 새 set을 돌려줘요. & (intersection) — 공통 요소만 담은 새 set을 돌려줘요. - (difference) — 주어진 enumerable의 요소를 제거한 self의 복사본을 돌려줘요. ^ — 둘 중 하나에만 있는 요소를 담은 새 set을 돌려줘요.
  • 비교: <=> — 비교 결과 -1/0/1을 돌려줘요. ==Object#eql?로 같은지 돌려줘요. compare_by_identity? — 아이덴티티로만 비교하는지 돌려줘요.
  • 조회: length(size), empty?, include?(member?, ===), subset?(<=), proper_subset?(<), superset?(>=), proper_superset?(>), disjoint?, intersect?.
  • 할당: add(<<), add?, merge, replace.
  • 삭제: clear, delete, delete?, subtract, delete_if, select!(filter!), keep_if, reject!.
  • 변환: classify, collect!(map!), divide, flatten, flatten!, inspect(to_s), join, to_a, to_set.
  • 반복: each.
  • 기타: reset — 내부 상태를 재설정해요.

Public Class Methods

[]( *ary )

주어진 객체들을 담은 새 set을 만들어요.

Set[1, 2]                   # => #<Set: {1, 2}>
Set[1, 2, 1]                # => #<Set: {1, 2}>
Set[1, 'c', :s]             # => #<Set: {1, "c", :s}>
new(enum = nil) { |o| ... }

주어진 enumerable 객체의 요소를 담은 새 set을 만들어요. 블록이 주어지면 enum의 요소가 블록으로 전처리돼요.

Set.new([1, 2])                       #=> #<Set: {1, 2}>
Set.new([1, 2, 1])                    #=> #<Set: {1, 2}>
Set.new(1..5)                         #=> #<Set: {1, 2, 3, 4, 5}>
Set.new([1, 2, 3]) { |x| x * x }      #=> #<Set: {1, 4, 9}>

Public Instance Methods

&(enum)

set과 주어진 enumerable 객체에 공통인 요소를 담은 새 set을 돌려줘요. intersection의 별칭이에요.

Set[1, 3, 5] & Set[3, 2, 1]             #=> #<Set: {3, 1}>
Set['a', 'b', 'z'] & ['a', 'b', 'c']    #=> #<Set: {"a", "b"}>
-(enum)

set을 복제한 뒤 주어진 enumerable 객체에 나타나는 모든 요소를 제거한 새 set을 돌려줘요. difference의 별칭이에요.

<=>(set)

두 set이 같으면 0, 주어진 set의 진부분집합/진상위집합이면 -1/+1, 둘 다 고유 요소를 가지면 nil을 돌려줘요.

==(other)

두 set이 같은지 true/false를 돌려줘요. 각 요소 쌍의 동등성은 Object#eql?에 따라 정의돼요.

===(o)

주어진 객체가 set의 멤버면 true, 아니면 false를 돌려줘요. case 문에서 쓰여요. include?의 별칭이에요.

^(enum)

set과 주어진 enumerable 객체 사이에서 한쪽에만 있는 요소를 담은 새 set을 돌려줘요. (set | enum) - (set & enum)과 동등해요.

add(o)

주어진 객체를 set에 추가하고 self를 돌려줘요. 한 번에 여러 요소는 merge를 쓰세요. <<의 별칭이에요.

add?(o)

주어진 객체를 set에 추가하고 self를 돌려줘요. 이미 set에 있으면 nil을 돌려줘요.

as_json(*)

Set#as_jsonSet.json_createSet 객체를 직렬화·역직렬화해요.

classify() { |o| ... }

주어진 블록 반환값으로 set을 분류하고 {value => set of elements} 해시를 돌려줘요. 블록이 없으면 열거자를 돌려줘요.

clear()

모든 요소를 제거하고 self를 돌려줘요.

collect!() { |o| ... }

collect()가 반환하는 값들로 요소를 교체해요. map!의 별칭이에요.

compare_by_identity()

set이 요소를 아이덴티티로 비교하게 만들고 self를 돌려줘요. Set의 모든 하위 클래스가 지원하지는 않을 수 있어요.

compare_by_identity?()

set이 요소를 아이덴티티로 비교하면 true를 돌려줘요.

delete(o)

주어진 객체를 set에서 삭제하고 self를 돌려줘요. 여러 항목은 subtract를 쓰세요.

delete?(o)

주어진 객체를 set에서 삭제하고 self를 돌려줘요. 없으면 nil을 돌려줘요.

delete_if() { |o| ... }

블록이 참으로 평가하는 모든 요소를 삭제하고 self를 돌려줘요.

disjoint?(set)

set과 주어진 enumerable에 공통 요소가 없으면 true를 돌려줘요. intersect?의 반대예요.

divide(&func)

주어진 블록이 정의하는 공통성에 따라 set을 부분집합들의 set으로 나눠요. 블록의 arity가 2면 block.call(o1, o2)가 참일 때 요소 o1, o2가 공통이고, 그 외에는 block.call(o1) == block.call(o2)일 때 공통이에요.

each(&block)

set의 각 요소에 대해 한 번씩 블록을 호출해요. 블록이 없으면 열거자를 돌려줘요.

empty?()

set에 요소가 없으면 true를 돌려줘요.

flatten()

각 포함 set을 재귀적으로 평탄화한 set의 복사본을 돌려줘요.

flatten!()

flatten과 동등하지만 결과로 receiver를 제자리에서 교체해요. 수정이 없으면 nil을 돌려줘요.

include?(o)

주어진 객체가 set의 요소면 true를 돌려줘요. member?, ===의 별칭이에요.

inspect()

요소를 보여주는 문자열을 돌려줘요. to_s의 별칭이에요.

intersect?(set)

set과 주어진 enumerable에 공통 요소가 있으면 true를 돌려줘요.

join(separator = $,)

주어진 레코드 구분자로 결합한, 모든 요소를 담은 문자열을 돌려줘요.

keep_if() { |o| ... }

블록이 참으로 평가하는 요소만 남기고 self를 돌려줘요.

length()

요소의 개수를 돌려줘요. size의 별칭이에요.

member?(o)

include?의 별칭이에요.

merge(*enums)

각 주어진 enumerable 객체의 요소를 set에 병합하고 self를 돌려줘요.

proper_subset?(set)

set이 주어진 set의 진부분집합이면 true를 돌려줘요. <의 별칭이에요.

proper_superset?(set)

set이 주어진 set의 진상위집합이면 true를 돌려줘요. >의 별칭이에요.

reject!() { |o| ... }

블록이 참으로 평가하는 요소를 삭제해요. 삭제가 있었으면 self를, 없으면 nil을 돌려줘요.

replace(enum)

set의 내용을 주어진 enumerable의 내용으로 교체해요.

reset()

내부 상태를 재설정해요. set 안의 요소인 동안 객체가 수정된 경우 유용해요.

select!() { |o| ... }

블록이 참으로 평가하지 않는 요소를 삭제해요. filter!의 별칭이에요. 삭제가 있었으면 self를, 없으면 nil을 돌려줘요.

subset?(set)

set이 주어진 set의 부분집합이면 true를 돌려줘요. <=의 별칭이에요.

subtract(enum)

주어진 enumerable 객체에 나타나는 모든 요소를 삭제하고 self를 돌려줘요.

superset?(set)

set이 주어진 set의 상위집합이면 true를 돌려줘요. >=의 별칭이에요.

to_a()

set을 배열로 변환해요. 요소 순서는 불확실해요.

to_json(*args)

self를 나타내는 JSON 문자열을 돌려줘요.

to_set(klass = Set, *args, &block)

인자 없이 호출하면 self를 돌려줘요. 그 외에는 set을 klass.new(self, *args, &block)으로 다른 set으로 변환해요.

|(enum)

set과 주어진 enumerable 객체의 요소를 병합한 새 set을 돌려줘요. +, union의 별칭이에요.

Set[1, 2, 3] | Set[2, 4, 5]         #=> #<Set: {1, 2, 3, 4, 5}>
Set[1, 5, 'z'] | (1..6)             #=> #<Set: {1, 5, "z", 2, 3, 4, 6}>