[모딥다] 37장. Set과 Map

vanLan·7일 전

모딥다

목록 보기
24/25
post-thumbnail

37장. Set과 Map

📁 Set

  • Set 객체는 중복되지 않은 유일한 값들을 집합.
  • 배열과 차이점:
    • 중복 값 X.
    • 요소 순서의 의미 X.
    • 인덱스로 요소에 접근 X.
  • 수학적 집합의 특성과 일치. ( 교집합, 차집합, 여집합 등 구현 가능 )

1. Set 객체의 생성

  • Set 생성자 함수로 생성. ( 인수 전달 X -> 빈 Set 객체 생성 )

    const set = new Set();
    console.log(set);  // Set(0) {}
  • Set 생성자 함수는 이터러블을 인수로 전달받아 Set 객체를 생성. ( 이때 중복된 값은 Set 객체에 요소로 저장 X )

    const set1 = new Set([1, 2, 3, 3]);
    console.log(set1);  // Set(3) {1, 2, 3}
    
    const set2 = new Set('string');
    console.log(set2);  // Set(6) {"s", "t", "r", "i", "n", "g"}
  • 배열의 중복 요소 제거시 사용 가능.

    const uniq = array => [...new Set(array)];
    console.log(uniq[2, 1, 2, 3, 4, 3, 4]);  // [2, 1, 3, 4]

2. 요소 개수 확인

  • 요소 개수를 확인할 때는 Set.prototype.size 프로퍼티를 사용.
    const { size } = new Set([1, 2, 3, 3]);
    console.log(size);
  • size 프로퍼티는 setter 함수 없이 getter 함수만 존재하는 접근자 프로퍼티이므로 직접적으로 요소 개수를 변경 불가.

3. 요소 추가

  • 요소 추가시에는 Set.prototype.add 메서드를 사용.

    const set = new Set();
    console.log(set);  // Set(0) {}
    
    set.add(1);
    console.log(set);  // Set(1) {1}
  • add 메서드는 새로운 요소가 추가된 Set 객체를 반환. ( 연속적 호출 가능 )

    const set = new Set();
    
    set.add(1).add(2);
    console.log(set);  // Set(2) {1, 2}
  • 객체나 배열과 같이 JS의 모든 값을 요소로 저장 가능.

    const set = new Set();
    
    set
      .add(1)
      .add('a')
      .add(true)
      .add(undefined)
      .add(null)
      .add({})
      .add([])
      .add(() => {});
    
    console.log(set);  // Set(8) {1, "a", true, undefined, null, {}, [], () => {}}

4. 요소 존재 여부 확인

  • 특정 요소 존재확인은 Set.prototype.has 메서드를 사용. ( 요소 존재 여부를 나타내는 불리언 값을 반환 )

    const set = new Set([1, 2, 3]);
    
    console.log(set.has(2));  // true
    console.log(set.has(4));  // false

5. 요소 삭제

  • 특정 요소 삭제시 Set.prototype.delete 메서드를 사용. ( 삭제 성공여부를 나타내는 불리언 값 반환 )

  • 인수로 삭제하려는 요소값을 전달.

    const set = new Set([1, 2, 3]);
    
    // 요소 2를 삭제
    set.delete(2);
    console.log(set);  // Set(2) {1, 3}
    
    // 요소 1을 삭제
    set.delete(1);
    console.log(set);  // Set(1) {3}
    
    // 존재하지 않는 요소 삭제시 에러없이 무시
    set.delete(0);
    console.log(set);  // Set(1) {3}

6. 요소 일괄 삭제

  • 모든 요소 일괄 삭제시 Set.prototype.clear 메서드를 사용. ( undefined를 반환 )

    const set = new Set([1, 2, 3]);
    
    set.clear();
    console.log(set);  // Set(0) {}

7. 요소 순회

  • Set 객체의 요소를 순회하려면 Set.prototype.forEach 메서드를 사용.
  • 인수 설명:
    • 1: 현재 순회 중인 요소값
    • 2: 현재 순회 중인 요소값
    • 3: 현재 순회 중인 Set 객체 자체
  • 첫 번째 인수와 두번째 인수는 같은 값이며, 이는 Array.prototype.forEach 메서드와 인터페이스를 통일하기 위함일 뿐 다른 의미는 없음.
  • Set 객체는 이터러블 이므로, for ...of 문으로 순회가 가능하며, 스프레드 문법과 배열 구조분해의 대상이 될 수 있음.
  • Set 객체는 요소의 순서에 의미를 갖지 않지만, 순회시에는 요소가 추가된 순서를 따름.

8. 집합 연산

  • Set 객체는 수학적 집합을 구현하기 위한 자료구조 임. ( 교집합, 합집합, 차집합 등을 구현 가능 )

🔹교집합

Set.prototype.intersection = function (set) {
  return new Set([...this].filter(v => set.has(v)));
};

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);

console.log(setA.intersection(setB));  // Set(2) {2, 4}
console.log(setB.intersection(setA));  // Set(2) {2, 4}

🔹합집합

Set.prototype.union = function (set) {
  return new Set([...this, ...set]);
};

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);

// SetA와 setB의 합집합
console.log(setA.union(setB));  // Set(4) {1, 2, 3, 4}
console.log(setB.union(setA));  // Set(4) {2, 4, 1, 3}

🔹차집합

Set.prototype.difference = function (set) {
  return new Set([...this].filter(v => !set.has(v)));
}

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);

// setA에 대한 setB의 차집합
console.log(setA.difference(setB));  // Set(2) {1, 3}
// setB에 대한 setA의 차집합
console.log(setB.difference(setA));  // Set(0) {}

🔹부분 집합과 상위 집합

// this가 subset의 상위 집합인지 확인
Set.prototype.inSuperset = function (subset) {
  const supersetArr = [...this];
  return [...subset].every(v => supersetArr.includes(v));
};

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);

// setA가 setB의 상위 집합인지 확인
console.log(setA.isSuperset);  // true
// setB가 setA의 상위 집합인지 확인
console.log(setB.isSuperset);  // false

📁 Map

  • 키와 값의 쌍으로 이루어진 컬렉션.
  • 객체와의 차이점:
    • 키로 객체를 포함한 모든 값을 사용 가능.
    • 이터러블 임.
    • 요소 개수 확인시 Map.prototype.size 사용.

1. Map 객체의 생성

  • Map 생성자 함수로 생성. ( 인수 전달 X -> 빈 Map 객체 생성 )

    const map = new Map();
    console.log(map);  // Map(0) {}
  • 이터러블을 인수로 전달받아 Map 객체를 생성. ( 이때 이터러블은 키와 값의 쌍으로 이루어진 요소로 구성되어야 함 )

    const map1 = new Map([['key1', 'value1'], ['key2', 'value2']]);
    console.log(map1);  // Map(2) {"key1" => "value1", "key2" => "value2"}
    
    const map2 = new Map([1, 2]);  // TypeError: Iterator value 1 is not an entry object
  • 전달된 이터러블에 중복된 키를 갖는 요소가 있으면, 값이 덮어써짐. ( 중복된 키를 갖는 요소 X )

    const map = new Map([['key1', 'value1'], ['key1', 'value2']]);
    console.log(map);  // Map(1) {"key1" => "value2"}

2. 요소 개수 확인

  • 요소 개수 확인시 Map.prototype.size 프로퍼티를 사용.
    const { size } = new Map([['key1', 'value1'], ['key2', 'value2']]);
    console.log(size);  // 2

3. 요소 추가

  • 요소 추가시 Map.prototype.set 메서드를 사용.

  • 마찬가지로 새로운 요소가 추가된 Map 객체를 반환함. ( 연속적으로 호출 가능 )

    const map = new Map();
    console.log(map);  // Map(0) {}
    
    map.set('key1', 'value1');
    console.log(map);  // Map(1) {"key1" => "value1"}
    
    map
      .set('key2', 'value2')
      .set('key3', 'value3');
    
    console.log(map);  // Map(3) {"key1" => "value1", "key2" => "value2", "key3" => "value3"}
  • 중복된 키를 갖는 요소가 존재할 수 없기 때문에 중복된 키를 갖는 요소를 추가하면 값이 덮어 써짐. ( 에러 발생 X )

    const map = new Map();
    
    map
      .set('key1', 'value1')
      .set('key2', 'value2');
    
    console.log(map);  // Map(1) {"key1" => "value2"}
  • Map 객체는 키 타입에 제한이 없으므로 객체를 포함한 모든 값을 키로 사용할 수 있음.

    const map = new Map();
    
    const lee = { name: 'Lee' };
    const kim = { name: 'Kim' };
    
    // 객체도 키로 사용 가능
    map
      .set(lee, 'developer')
      .set(kim, 'designer');
    
    console.log(map);  // Map(2) { {name: "Lee"} => "developer", {name: "Kim"} => "designer" }

4. 요소 취득

  • 특정 요소를 취득하기 위해 Map.prototype.get 메서드를 사용.

  • 인수로 키를 전달하면 전달한 키가 갖는 값을 반환. ( 존재하지 않을 시 undefined 반환 )

    const map = new Map();
    
    const lee = { name: 'Lee' };
    const kim = { name: 'Kim' };
    
    // 객체도 키로 사용 가능
    map
      .set(lee, 'developer')
      .set(kim, 'designer');
    
    console.log(map.get(lee));  // developer
    console.log(map.get('key'));  // undefined

5. 요소 존재 여부 확인

  • 특정 요소가 존재하는지 확인하려면 Map.prototype.has 메서드를 사용. ( 특정 요소의 존재 여부를 나타낸는 불리언 값을 반환 )

    const lee = { name: 'Lee' };
    const kim = { name: 'Kim' };
    
    const map = new Map([[lee, 'developer'], [kim, 'designer']]);
    
    console.log(map.has(lee));  // true
    console.log(map.has('key'));  // false

6. 요소 삭제

  • 객체의 요소를 삭제하려면 Map.prototype.delete 메서드를 사용. ( 삭제 성공 여부를 나타내는 불리언 값을 반환 )

  • 존재하지 않는 키로 Map 요소를 삭제하려면 에러 없이 무시됨.

  • 불리언 값을 반환하므로 연속적으로 호출은 불가.

    const lee = { name: 'Lee' };
    const kim = { name: 'Kim' };
    
    const map = new Map([[lee, 'developer'], [kim, 'designer']]);
    
    map.delete(kim);
    console.log(map);  // Map(1) { { name: "Lee" } => "developer" }

7. 요소 일괄 삭제

  • 요소 일괄 삭제시 Map.prototype.clear 메서드를 사용. ( 언제나 undefined를 반환 )

    const lee = { name: 'Lee' };
    const kim = { name: 'Kim' };
    
    const map = new Map([[lee, 'developer'], [kim, 'designer']]);
    
    map.clear();
    console.log(map);  // Map(0) {}

8. 요소 순횐

  • 요소 순회시 Map.prototype.forEach 메서드를 사용.

  • 인수 설명:

    • 1: 현재 순회 중인 요소값
    • 2: 현재 순회 중인 요소키
    • 3: 현재 순회 중인 Map 객체 자체
  • Map 객체는 이터러블이므로, for ...of 문으로 순회가 가능하며, 스프레드 문법과 배열 구조분해 할당의 대상이 될 수 있음.

  • Map객체는 이터러블이면서 동시에 이터레이터인 객체를 반환하는 메서드를 제공.

    • Map.prototype.keys: Map 객체에서 요소키를 값으로 갖는 이터러블이면서 동시에 이터레이터인 객체를 반환.
    • Map.prototype.values: Map 객체에서 요소값을 값으로 갖는 이터러블이면서 동시에 이터레이터인 객체를 반환.
    • Map.prototype.entries: Map 객체에서 요소키와 요소값을 값으로 갖는 이터러블이면서 동시에 이터레이터인 객체를 반환.
    const lee = { name: 'Lee' };
    const kim = { name: 'Kim' };
    
    const map = new Map([[lee, 'developer'], [kim, 'designer']]);
    
    // 요소키를 값으로 갖는 이터레이터를 반환
    for (const key of map.keys()) {
      console.log(key);  // {name: "Lee"} {name: "Kim"}
    }
    
    // 요소값을 값으로 갖는 이터레이터를 반환
    for (const value of map.values()) {
      console.log(value);  // developer designer
    }
    
    // 요소키와 요소값을 값으로 갖는 이터레이터를 반환
    for (const entry of map.entries()) {
      console.log(entry);  // [{name: "Lee"}, "developer"] [{name: "Kim"}, "designer"]
    }
  • Map 객체는 요소의 순서에 의미를 갖지 않지만 순회시에는 요소가 추가된 순서를 따름.

profile
프론트엔드 개발자를 꿈꾸는 이

0개의 댓글