본문 바로가기
Frontend/JavaScript

[JavaScript] Set

by 모너아링 2023. 2. 16.

Set

  • 중복되지 않는 유일한 값들의 집합
  • 요소에 순서가 없다.
  • 인덱스로 요소에 접근할 수 없다.

Set 객체 생성

const set1 = new Set();
console.log(set); // Set(0) {}

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

const set3 = new Set('hello');
console.log(set); // Set(4) {"h", "e", "l", "o"}
//중복 제거
const uniq = array => array.filter((v, i, self) => self.indexOf(v) === i);
const uniq = array => [ ... new Set(array)];
// 두 코드 실행 시 동일한 결과 출력

console.log(uniq([2, 1, 2, 3, 4, 3, 4]); // [2, 1, 3, 4]

요소 개수 확인

  • Set.prototype.size 프로퍼티 사용
const { size } = new Set([1, 2, 3, 3]);

const set = new Set([1, 2, 3]);

set.size = 10; // 무시(변경 불가)
console.log(set.size); // 3
  • size 프로퍼티는 setter 함수 없이 getter 함수만 존재

요소 추가

  • Set.prototype.add 메소드 사용
const set = new Set();

set.add(1);
console.log(set); // Set(1) {1}

//연속적 호출 가능
set.add(1).add(2);
console.log(set); // Set(3) {1, 2}

//중복된 요소 추가 무시
set.add(1).add(2).add(2);
console.log(set); // Set(2) {1, 2}

set.add(NaN).add(NaN); // 중복 추가 무시
set.add(0).add(-0); // 중복 추가 무시
console.log(set); // Set(2) {NaN, 0}
  • === 연산자는 NaN을 다르다고 평가
  • Set 객체는 NaN을 같다고 평가
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, {}, [], () => {}}
  • 자바스크립트의 모든 값을 요소로 저장 가능

요소 존재 여부 확인

  • Set.prototype.has 메서드 사용
const set = new Set([1, 2, 3]);

console.log(set.has(2)); // true
console.log(set.has(4)); // false

요소 삭제

  • Set.prototype.delete 메서드 사용
const set = new Set([1, 2, 3]);

set.delete(2);
console.log(set); // Set(2) {1, 3}

//존재하지 않는 값 삭제 시 무시
set.delete(0);

//연속 호출 불가
set.delete(1).delete(3); // TypeError

//일괄 삭제
//clear 메서드 사용
set.clear();
console.log(set); // Set(0) {}

요소 순회

  • Set.prototype.forEach 메서드 사용
  • 콜백 함수의 인수
    • 첫 번째 인수: 현재 순회 중인 요소 값
    • 두 번째 인수: 현재 순회 중인 요소 값
    • 세 번째 인수: 현재 순회 중인 Set 객체 자체
const set = new Set([1, 2, 3]);

set.forEach((v, v2, set) => console.log(v, v2, set));
/*
1 1 Set(3) {1, 2, 3}
2 2 Set(3) {1, 2, 3}
3 3 Set(3) {1, 2, 3}
*/
  • Set 객체는 이터러블
const set = new Set([1, 2, 3]);

console.log(Symbol.iterator in set); // true

//for...of 문 순회 가능
for(const value of set){
    console.log(value); // 1 2 3
}

//스프레드 문법
console.log([ ...set]); // [1, 2, 3]

//배열 디스트럭처링 할당
const [a, ...rest] = set;
console.log(a, rest); // 1, [2, 3]

집합 연산

//교집합

//첫 번째 방법
Set.prototype.intersection = function (set) {
    const result = new Set();

    for(const value of set) {
        //this는 set
        //set이 value 값을 가지고 있으면 result에 추가
        if(this.has(value)) result.add(value);
    }
    return result;
};

//두 번째 방법
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) {
    // this(Set 객체)를 복사
    const result = new Set(this);

    for(const value of set) {
        result.add(value);
    }
    return result;
};

//두 번째 방법
Set.prototype.union= function(set) {
    return new Set([ ...this, ...set]);
}

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

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

//첫 번째 방법
Set.prototype.difference= function (set) {
    const result = new Set(this);

    for(const value of set) {
        result.delete(value);
    }
    return result;
};

//두 번째 방법
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]);

console.log(setA.difference(setB)); // Set(2) {1, 3}
console.log(setB.difference(setA)); // SEt(0) {}
//부분 집합과 상위 집합

//첫 번째 방법
Set.prototype.isSuperset= function (subset) {
//this가 subset의 상위 집합인지 확인
    for(const value of set) {
        //superset의 모든 요소가 subset의 모든 요소를 포함하지 않는다면 false 반환
        if(!this.has(value)) return false;
    }
    return true;
};

//두 번째 방법
Set.prototype.isSuperset= function(set) {
    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(setB)); // true
// setB가 setA의 상위 집합인지 확인
console.log(setB.isSuperset(setA)); // false

forEach / map / every 차이

  • forEach()
    • 아무 것도 반환하지 않음
  • map()
    • 작업 수행한 새 객체 배열 반환
  • every()
    • boolean 값 반환

'Frontend > JavaScript' 카테고리의 다른 글

[JavaScript] 제너레이터와 async/await  (0) 2023.02.16
[JavaScript] DOM 이벤트  (0) 2023.02.16
[JavaScript] 이터러블  (1) 2023.02.16
[JavaScript] 함수와 일급 객체  (0) 2022.11.08
[JavaScript] 객체 리터럴  (1) 2022.11.08