λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
🍎 iOS/Swift

[Swift] Collection Type - 집합(Set), 집합 μ—°μ‚°, 반볡, μ •λ ¬

by Danna 2021. 5. 31.
728x90
728x90

μ•ˆλ…•ν•˜μ„Έμš”! 이번 ν¬μŠ€νŒ…μ€ Swift 데이터ꡬ쑰와 μ•Œκ³ λ¦¬μ¦˜ μ±…μ˜ 2μž₯ μŠ€ν„°λ”” μ€‘ λ‘λ²ˆμ§Έ 핡심 λ‚΄μš©μΈ Collection Type 에 λŒ€ν•œ λ‚΄μš©μž…λ‹ˆλ‹€. Array (λ°°μ—΄), Dictionary (λ”•μ…”λ„ˆλ¦¬, μ‚¬μ „ν˜•), Set (집합), Tuple(νŠœν”Œ) 넀가지 νƒ€μž…μ— λŒ€ν•΄ ν•™μŠ΅ν–ˆμŠ΅λ‹ˆλ‹€.


🍑 집합(Set)

Set 은 μ„œλ‘œ μ€‘λ³΅λ˜μ§€ μ•Šκ³ , nil 이 ν¬ν•¨λ˜μ§€ μ•Šμ€ μˆœμ„œκ°€ μ—†λŠ” μ»¬λ ‰μ…˜μž…λ‹ˆλ‹€. Set λŠ” μˆ˜ν•™μ—μ„œμ˜ μ§‘ν•©μ˜ κ°œλ…μ„ 기반으둜 λ§Œλ“  데이터 νƒ€μž…μ΄λΌκ³  ν•©λ‹ˆλ‹€. Set 의 λ°μ΄ν„°λŠ” Dictionary의 Key 와 λ§ˆμ°¬κ°€μ§€λ‘œ Hashable ν”„λ‘œν† μ½œμ„ λΆ€ν•©ν•΄μ•Ό ν•©λ‹ˆλ‹€! κΈ°λ³Έ 데이터 νƒ€μž… 외에 μ»€μŠ€ν…€ νƒ€μž…λ„ 지정할 수 μžˆμ§€λ§Œ, 이 경우 Hashable ν”„λ‘œν† μ½œμ„ λΆ€ν•©ν•˜λ„λ‘ λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€. 

 

Set 은 배열보닀 효율적이고, 데이터 μ ‘κ·Ό 속도가 λΉ λ₯΄λ‹€κ³  ν•©λ‹ˆλ‹€. Hashable ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜κΈ° λ•Œλ¬Έμ΄ μ•„λ‹κΉŒμš”? 😢!! λ°°μ—΄μ˜ 크기가 n 일 λ•Œ, λ°°μ—΄ μš”μ†Œ 검색 μ‹œ μ΅œμ•…μ˜ μ‹œκ°„λ³΅μž‘λ„λŠ” O(n) μ΄μ§€λ§Œ Set 의 경우 크기에 상관없이 O(1) 을 μœ μ§€ν•œλ‹€κ³  ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ λ°°μ—΄μ—μ„œ μš”μ†Œμ˜ μˆœμ„œκ°€ μ€‘μš”ν•˜μ§€ μ•Šκ³ , ν•œ 번만 λ‚˜νƒ€λ‚˜λ„ λ˜λŠ” 경우, Array λŒ€μ‹  Set 을 μ΄μš©ν•˜λŠ” 것이 νš¨μœ¨μ μž…λ‹ˆλ‹€!

 

βœ”οΈŽ Set μ΄ˆκΈ°ν™”

  • λΉ„μ–΄μžˆλŠ” Set μ΄ˆκΈ°ν™” μ‹œ, λ°°μ—΄κ³Ό ν˜Όλ™λ˜μ§€ μ•ŠκΈ° μœ„ν•΄ μΆ•μ•½ν˜•μ„ μ œκ³΅ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  ν•©λ‹ˆλ‹€! Set νƒ€μž…μž„μ„ λͺ…μ‹œν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • λ°°μ—΄ μš”μ†Œλ‘œ Set μ΄ˆκΈ°ν™” μ‹œ, Set 의 μš”μ†Œ νƒ€μž…μ„ μƒλž΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
// Creates an empty set
var stringSet = Set<String>()

// Creating a Set with an Array Literal
var stringSet1: Set<String> = ["A", "B", "C"]
var stringSet2: Set = ["A", "B", "C"]

 

βœ”οΈŽ Set μš”μ†Œ μΆ”κ°€, μš”μ†Œκ°€ μžˆλŠ”μ§€ 확인

  • insert(_:) λ©”μ†Œλ“œλ‘œ μƒˆλ‘œμš΄ μš”μ†Œλ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€. 

    • λ©”μ†Œλ“œ λ°˜ν™˜κ°’μ€ (inserted, memberAfterInsert) 
    • inserted :: Set 에 μƒˆλ‘œμš΄ μš”μ†Œκ°€ μΆ”κ°€λ˜μ—ˆλŠ”μ§€μ— λŒ€ν•œ Bool νƒ€μž… - true / false
    • memberAfterInsert :: μΆ”κ°€ν•˜λ €λŠ” κ°’. μƒˆλ‘œ μΆ”κ°€λœ 경우 μƒˆλ‘­κ²Œ μΆ”κ°€λœ κ°’ / μΆ”κ°€λ˜μ§€ μ•Šμ•˜λ‹€λ©΄ κΈ°μ‘΄ κ°’

  • contains(_:) λ©”μ†Œλ“œλ‘œ νŠΉμ • μš”μ†Œκ°€ Set 에 ν¬ν•¨λ˜μ–΄μžˆλŠ”μ§€ μ•Œ 수 μžˆλ‹€. λ°˜ν™˜κ°’μ€ Bool νƒ€μž…
stringSet.insert("A")
// (inserted: true, memberAfterInsert: "A")

stringSet.insert("A")
// (inserted: false, memberAfterInsert: "A")

stringSet.contains("B")
// false

 

βœ”οΈŽ Set μš”μ†Œ μ‚­μ œ

  • remove(_:) λ©”μ†Œλ“œλŠ” νŠΉμ • μš”μ†Œλ₯Ό μ‚­μ œν•œλ‹€.

    • νŠΉμ • μš”μ†Œμ˜ 값을 미리 μ•Œκ³  μžˆμ–΄μ•Ό ν•œλ‹€.
    • νŠΉμ • μš”μ†Œκ°€ μžˆλ‹€λ©΄ κ·Έ 값을 리턴, μ—†λ‹€λ©΄ nil 을 λ¦¬ν„΄ν•œλ‹€.

  • remove(at:) λ©”μ†Œλ“œλŠ” νŠΉμ • 인덱슀의 μš”μ†Œλ₯Ό μ‚­μ œν•œλ‹€.

    • μ΄λ•Œ μΈλ±μŠ€λŠ” λ°°μ—΄μ—μ„œμ˜ Int κ°€ μ•„λ‹Œ Set.Index 값이닀.
    • firstIndex(of:) λ©”μ†Œλ“œ λ“±κ³Ό ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆλ‹€.

  • removeFirst() λ©”μ†Œλ“œλŠ” Set 의 첫번째 μš”μ†Œλ₯Ό μ‚­μ œν•œλ‹€.

    • Set 은 μˆœμ„œκ°€ μ§€μ •λ˜μ§€ μ•Šμ€ μ»¬λ ‰μ…˜μ΄λ―€λ‘œ, μ΄ˆκΈ°ν™”μ‹œ λ°°μ—΄μ˜ 첫번째 μš”μ†Œμ™€ λ‹€λ₯Ό 수 μžˆλ‹€.

  • removeAll(), removeAll(keepCapacity:) λ©”μ†Œλ“œλŠ” 전체 μš”μ†Œλ₯Ό μ‚­μ œν•œλ‹€.

    • keepCapacity λŠ” bool νƒ€μž…μ˜ κ°’μœΌλ‘œ, true 인 경우 Set 의 μš©λŸ‰(capacity)은 κ°μ†Œν•˜μ§€ μ•ŠλŠ”λ‹€.
    • removeAll() λ©”μ†Œλ“œλ₯Ό μ œμ™Έν•˜κ³ λŠ” capacity κ°€ κ°μ†Œν•˜μ§€ μ•Šμ•˜λ‹€.
var stringSet1: Set<String> = ["A", "B", "C", "D"]
// {"A", "D", "B", "C"}

// νŠΉμ • μš”μ†Œ μ‚­μ œ
stringSet1.remove("A")

// νŠΉμ • 인덱슀의 μš”μ†Œ μ‚­μ œ
if let idx = stringSet1.firstIndex(of: "C") {
    stringSet1.remove(at: idx)
}

// Set 의 첫번째 μš”μ†Œ μ‚­μ œ 
stringSet1.removeFirst() // "D" κ°€ μ‚­μ œλœλ‹€.

// Set 의 λͺ¨λ“  μš”μ†Œ μ‚­μ œ 
stringSet1.capacity // 6 :: 4 + 2(μ—¬μœ κ³΅κ°„)
stringSet1.removeAll(keepingCapacity: true)
stringSet1.capacity // 6으둜 ν•¨μˆ˜ ν˜ΈμΆœμ „κ³Ό κ°™λ‹€.

 

βœ”οΈŽ Set μš”μ†Œ μ •λ ¬ν•΄μ„œ λ°˜λ³΅ν•˜κΈ°

  • for ... in λ¬Έλ²•μœΌλ‘œ Set 의 μš”μ†Œλ₯Ό μˆœνšŒν•  수 μžˆλ‹€. μ΄λ•Œ μ§€μ •λœ μˆœμ„œλŠ” μ—†λ‹€.
  • Set.sorted() λ©”μ†Œλ“œ 호좜둜 Set을 μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬ν•  수 μžˆλ‹€. μ •λ ¬λœ 배열이 λ°˜ν™˜λœλ‹€.
  • Set.sorted(by: {$0 > $1 }) λ©”μ†Œλ“œ 호좜둜 Set 을 λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ν•  수 μžˆλ‹€. μ •λ ¬λœ 배열이 λ°˜ν™˜λœλ‹€.
var nameSet: Set<String> = ["Sally", "Mary", "Michael", "Brown"]

// Set μš”μ†Œ 반볡문으둜 μˆœνšŒν•˜κΈ°
// Michael - Brown -Sally - Mary μˆœμ„œλ‘œ μˆœνšŒλ˜μ—ˆλ‹€.
for name in nameSet {
    print(name)
}

// Set μš”μ†Œ μ •λ ¬ν•΄μ„œ 반볡 μˆœνšŒν•˜κΈ°
// Brown - Mary - Michael - Sally 으둜 μ•ŒνŒŒλ²³ μ‚¬μ „μˆœμœΌλ‘œ μ •λ ¬λœλ‹€.
for name in nameSet.sorted() {
    print(name)
}

// Set μš”μ†Œ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ν•˜κΈ°
// ["Sally", "Michael", "Mary", "Brown"]
nameSet.sorted(by: { $0 > $1 }))

 

πŸ’‘ Set 집합 μ—°μ‚° ν•¨μˆ˜ μ΄μš©ν•˜κΈ°

Set 은 μˆ˜ν•™μ—μ„œμ˜ 집합 κ°œλ…μ„ 기반으둜 λ§Œλ“  νƒ€μž…μœΌλ‘œ, 집합 κ΅¬μ‘°λ‚˜ 연산이 ν•„μš”ν•  λ•Œ μ μš©ν•˜λ©΄ 쒋은 νƒ€μž…μž…λ‹ˆλ‹€. 두 집합간 연산을 μœ„ν•΄ 합집합, ꡐ집합, 여집합, 차집합 λ©”μ†Œλ“œλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. 각 μ—°μ‚°λ§ˆλ‹€ μƒˆλ‘œμš΄ Set 을 λ§Œλ“€μ–΄ λ°˜ν™˜ν•˜λŠ” λ©”μ†Œλ“œ, 원본 Set 을 μ—…λ°μ΄νŠΈ ν•˜λŠ” λ©”μ†Œλ“œ μ΄λ ‡κ²Œ 두 κ°œκ°€ μ‘΄μž¬ν•΄μš”! λ©”μ†Œλ“œμ˜ μΈμžλŠ” Array, Set λͺ¨λ‘ κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

  • Set 의 동등연산 (==) λŠ” λ‚΄λΆ€ μš”μ†Œκ°€ κ°™μœΌλ©΄ λ™λ“±ν•˜λ‹€κ³  νŒλ‹¨ν•©λ‹ˆλ‹€. μˆœμ„œκ°€ μ—†κΈ° λ•Œλ¬Έμ— μš”μ†Œλ§Œ λΉ„κ΅ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

  • 합집합 (A∪B) :: 두 집합에 μžˆλŠ” μš”μ†Œλ₯Ό λͺ¨λ‘ ν¬ν•¨μ‹œν‚¨λ‹€.

    • union(_:) λ©”μ†Œλ“œλŠ” 두 Set 의 ν•©μ§‘ν•©μœΌλ‘œ μƒˆλ‘œμš΄ Set 을 λ§Œλ“€μ–΄ λ°˜ν™˜ν•œλ‹€.
    • formUnion(_:) λ©”μ†Œλ“œλŠ” 두 Set 의 ν•©μ§‘ν•©μœΌλ‘œ 원본 Set 을 μ—…λ°μ΄νŠΈν•œλ‹€.
    • A.formUnion(B) = A 에 μ—†λŠ” B의 μš”μ†Œλ₯Ό μΆ”κ°€ν•œλ‹€.

  • ꡐ집합 (A∩B) :: 두 집합에 κ³΅ν†΅μ μœΌλ‘œ μžˆλŠ” μš”μ†Œλ₯Ό ν¬ν•¨μ‹œν‚¨λ‹€.

    • intersection(_:) λ©”μ†Œλ“œλŠ” 두 Set 의 κ΅μ§‘ν•©μœΌλ‘œ μƒˆλ‘œμš΄ Set 을 λ§Œλ“€μ–΄ λ°˜ν™˜ν•œλ‹€.
    • formIntersection(_:) λ©”μ†Œλ“œλŠ” 두 Set 의 κ΅μ§‘ν•©μœΌλ‘œ 원본 Set 을 μ—…λ°μ΄νŠΈν•œλ‹€.
    • A.formIntersection(b) = A 에 μžˆλŠ” B의 μš”μ†Œλ₯Ό μ‚­μ œν•œλ‹€.

  • 여집합 (A∪B - A∩B) :: 두 μ§‘ν•©μ˜ 전체 μ§‘ν•©μ—μ„œ 두 집합에 κ³΅ν†΅μœΌλ‘œ μžˆλŠ” μš”μ†Œλ₯Ό μ œμ™Έν•œλ‹€.

    • symmetricDifference(_:) λ©”μ†Œλ“œλŠ” 두 Set 의 μ—¬μ§‘ν•©μœΌλ‘œ μƒˆλ‘œμš΄ Set 을 λ§Œλ“€μ–΄ λ°˜ν™˜ν•œλ‹€.
    • formSymmetricDifference(_:) λ©”μ†Œλ“œλŠ” 두 Set 의 μ—¬μ§‘ν•©μœΌλ‘œ 원본 Set 을 μ—…λ°μ΄νŠΈν•œλ‹€.

  • 차집합 (A-B) :: A μ§‘ν•©μ—μ„œ B μ§‘ν•©μ˜ μ›μ†Œλ₯Ό μ œμ™Έν•œλ‹€.

    • subtracting(_:) λ©”μ†Œλ“œλŠ” 원본 Set μ—μ„œ 주어진 Set 에 ν¬ν•¨λ˜μ§€ μ•ŠλŠ” μ›μ†Œλ‘œ μƒˆλ‘œμš΄ Set 을 λ§Œλ“€μ–΄ λ°˜ν™˜ν•œλ‹€.
    • subtract(_:) λ©”μ†Œλ“œλŠ” 원본 Set μ—μ„œ 주어진 Set 의 μ›μ†Œλ₯Ό μ‚­μ œν•œλ‹€.
// Set μ—°μ‚°
var A: Set = ["A", "B", "C", "D"]
let B: Set = ["C", "D", "E", "F"]

// 합집합 ["B", "E", "D", "A", "C", "F"]
let unionSet = A.union(B)

// ꡐ집합 ["C", "D"]
let intersectionSet = A.intersection(B)

// 여집합 ["B", "E", "A", "F"]
let complementSet = A.symmetricDifference(B)

// 차집합 ["B", "A"]
let subtractSet = A.subtracting(B)

합집합 / ꡐ집합 / 여집합 / 차집합

 

βœ”οΈŽ Set 의 λ„μš°λ―Έ λ©”μ†Œλ“œλ“€

  • isSubset(of:) λ©”μ†Œλ“œλŠ” 원본 Set 이 주어진 Set 의 λΆ€λΆ„ 집합인지 확인해 Bool 값을 λ°˜ν™˜ν•œλ‹€.

  • isStrictSubset(of:) λ©”μ†Œλ“œλŠ” λ™λ“±ν•œ Set 이 μ•„λ‹Œ λΆ€λΆ„ 집합인지 확인해 Bool 값을 λ°˜ν™˜ν•œλ‹€.

    • 뢀뢄집합이 μ•„λ‹ˆκ±°λ‚˜ 동등할 경우 False, λ™λ“±ν•˜μ§€ μ•Šκ³  뢀뢄집합인 경우 True
  • isSuperset(of:) λ©”μ†Œλ“œλŠ” 원본 Set 이 주어진 Set 의 μƒμœ„μ§‘ν•©μΈμ§€ 확인해 Bool 값을 λ°˜ν™˜ν•œλ‹€.

    • isSubset λ©”μ†Œλ“œμ™€ λ°˜λŒ€λ˜λŠ” κ°œλ…μ΄λ‹€.
  • isStrictSuperset(of:) λ©”μ†Œλ“œλŠ” λ™λ“±ν•œ Set 이 μ•„λ‹Œ μƒμœ„ 집합인지 확인해 Bool 값을 λ°˜ν™˜ν•œλ‹€.

  • isDisjoint(with:) λ©”μ†Œλ“œλŠ” 두 Set 의 곡톡 μš”μ†Œκ°€ μ—†λŠ”μ§€ 확인해 Bool 값을 λ°˜ν™˜ν•œλ‹€.

    • κ³΅ν†΅μš”μ†Œκ°€ μ—†μœΌλ©΄ True , κ³΅ν†΅μš”μ†Œκ°€ 있으면 False

let A: Set = ["A", "B", "C", "D"]
let B: Set = ["C", "D", "E", "F"]
let C: Set = ["A", "B"]

// 뢀뢄집합인지 λΉ„κ΅ν•˜κΈ°
A.isSubset(of: C) // false
C.isSubset(of: A) // true

// μ™„μ „ν•œ 뢀뢄집합인지 λΉ„κ΅ν•˜κΈ°
let D: Set = ["A", "B", "C", "D"]
B.isStrictSubset(of: A) // false
C.isStrictSubset(of: A) // true
D.isStrictSubset(of: A) // false

// μƒμœ„μ§‘ν•©μΈμ§€ λΉ„κ΅ν•˜κΈ°
A.isSuperset(of: C) // true
A.isStrictSuperset(of: D) // false

// κ³΅ν†΅μš”μ†Œκ°€ μ—†λŠ”μ§€ ν™•μΈν•˜κΈ°
A.isDisjoint(with: C) // false
A.isDisjoint(with: ["E", "F"]) // true

참고 링크

728x90
728x90