Set과 Map이란?

오호·2022년 2월 7일
0
post-thumbnail
post-custom-banner

프로젝트를 진행하거나 실무에서 SetMap을 유용하다고 생각해본적이 없는 것 같다. 항상 언제 쓰는지 궁금증이 있었는데 개념을 공부해보고 유즈케이스에 대해서도 알아보려 한다.

먼저 Set에 대해서 알아보자.

1. Set

자바스크립트의 데이터타입은 크게 두 가지로 나뉘어진다.

크게 원시타입과 객체타입으로 나뉘어지는데 숫자, 문자열, null, undefined, boolean, symbol을 제외한 모든 타입은 객체 타입이다. 따라서 Set도 마찬가지로 객체라고 할 수 있다

일반 객체와 무엇인가 다르기 때문에 나누어두었다고 생각이 든다.
Set객체는 중복되지 않는 유일한 값들의 집합이다. 배열과 유사하지만 다음의 차이를 가진다.

  • Set 객체는 동일한 값을 중복하여 포함할 수 없다.
  • 요소 순서에 의미가 없다.
  • 인덱스로 요소에 접근할 수 없다.

1.1 Set 객체의 생성

Set 객체는 생성자 함수로 생성한다.

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

Set 생성자 함수는 이터러블을 인수로 전달받아 Set 객체를 생성한다. 이 때 이터러블의 중복된 값은 Set 객체에 요소로 저장되지 않는다

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

const sampleSet2 = new Set('hello');
console.log(sampleSet2); // Set(4) {"h", "e", "l", "o"}

이러한 특성 때문에 알고리즘을 공부할 때 Set을 이용해서 간단하게 배열의 중복을 제거하기도 한다 👍

const filtered = [...new Set([1,2,2,2,3])];
console.log(filtered); // [1, 2, 3];

1.2 요소 개수 확인

Set 객체의 요소 개수를 확인할 때는 Set.prototype.size를 사용한다.

const newSet = new Set([1, 2, 3, 4, 5, 5]);
console.log(newSet.size); // 5

size 프로퍼티는 setter 가 없이 getter만 존재하는 접근자이다. 따라서 할당으로 값을 변경할 수 없다.

1.3 요소 추가

요소를 추가할 때는 Set.prototype.add를 사용한다.

const newSet = new Set();
console.log(newSet); // Set(0) {}
newSet.add(1).add(2).add(3);
console.log(newSet); // Set(3) {1, 2, 3}

add 메서드는 새로운 요소가 추가된 Set 객체를 반환한다. 따라서 add 메서드 이후에 체이닝해서 사용할 수 있다.

Set 객체는 일반 객체와 배열과 같이 js의 모든 값을 추가할 수 있다

const newSet = new Set();
newSet
  .add(1)
  .add('h')
  .add(true)
  .add(undefined)
  .add(null)
  .add([])
  .add(function hello() {})
  .add({});

console.log(newSet); 

// Set(8) { 1, 'h', true, undefined, null, [], [Function: hello], {} }

1.4 요소 존재 여부 확인

Set.prototype.has 메서드를 사용한다.

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

console.log(newSet.has(3)); // true

1.5 요소 삭제

Set.prototype.delete 메서드를 사용한다.

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

1.6 모든 요소 삭제

Set.prototype.clear를 하면 모든 요소를 제거할 수 있다.

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

1.7 요소 순회

Set객체를 순회할 수 있는데 Set.prototype.forEach 메서드를 사용할 수 있다.
3개의 인수를 전달 받는다.
1. 현재 순회 중인 요소값
2. 현재 순회 중인 요소값
3. 현재 순회 중인 Set 객체 자체

1번 인수와 2번째 인수는 같다.

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

newSet.forEach((v, v2, set) => console.log(v, v2, set));

Set은 이터러블이기 때문에 for of문을 사용할 수 있고 스프레드와 디스트럭처링 또한 가능하다.

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

for (const value of newSet) {
  console.log(value);
}

console.log([...newSet]);
const [a, ...rest] = newSet;
console.log(a, rest);

// 1
// 2
// 3
// [ 1, 2, 3 ]
// 1 [ 2, 3 ]

1.8 집합 연산

Set 객체는 수학적 집합을 구현하기 위한 자료구조이다. 교집합, 합집합, 차집합등을 구현할 수 있다.

1.8.1 교집합

다음과 같이 흉내 내볼 수 있다.

Set.prototype.intersection = function (set) {
  const result = new Set();

  for (const val of set) {
    if (this.has(val)) result.add(val);
  }

  return result;
};

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

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

1.8.2 합집합

Set.prototype.union = function (set) {
  const result = new Set(this);

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

  return result;
};

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([5, 6, 7, 8]);
console.log(setA.union(setB));

// Set(8){1,2,3,4,5,6,7,8}

1.8.3 차집합

Set.prototype.difference = function (set) {
  const result = new Set(this);

  for (const val of set) {
    if (this.has(val)) result.delete(val);
  }
  return result;
};

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

console.log(setA.difference(setB));
// Set (2) {1,3}

2. Map

Map또한 객체이다. Map은 키와 값의 쌍으로 이루어진 컬렉션이다. 객체와 유사하지만 다음의 차이를 가진다.

  1. 객체를 포함한 모든 값을 키로 사용할 수 있다.
  2. 이터러블이다.

2.1 Map 객체의 생성

Map 객체는 Map 생성자 함수로 생성한다.

const map = new Map();
console.log(map); // Map(0) {}

Map 생성자 함수는 이터러블을 인수로 전달받아 Map객체를 생성한다. 이 때 인수로 전달되는 이터러블은 키와 값의 쌍으로 이루어진 요소로 구성어야 함

const map = new Map([
  ['key1', 'value1'],
  ['key2', 'value2'],
]);

console.log(map); // Map(2) { 'key1' => 'value1', 'key2' => 'value2' }

2.2 요소 개수 확인

Map.prototype.size 프로퍼티를 사용한다.
Set과 같이 getter만 존재한다.

const map = new Map([
  ['key1', 'value1'],
  ['key2', 'value2'],
]);

console.log(map.size); // 2

2.3 요소 추가

Map.prototype.set메서드를 사용한다.

const map = new Map();
console.log(map);

map.set('key1', 'value1').set('key2', 'value2');
console.log(map); // Map(2) { 'key1' => 'value1', 'key2' => 'value2' }

map은 키 타입의 제한이 없다

2.4 요소 취득

Map.prototype.get메서들르 사용한다.

const map = new Map();
const leo = { name: 'Leo' };
const kim = { name: 'Kim' };

map.set(leo, 'developer').set(kim, 'designer');

console.log(map.get(leo)); // developer

2.5 요소 존재 여부 확인

Map.prototype.has를 사용한다.

2.6 요소 삭제

Map.prototype.delete 메서드를 사용한다.

2.7 요소 전체 삭제

Map.prototype.clear 메서드를 사용한다.

2.8 요소 순회

Set 과 마찬가지로 Map.prototype.forEach메서드를 사용한다.

const leo = { name: 'Leo' };
const kim = { name: 'Kim' };

const map = new Map([
  [leo, 'developer'],
  [kim, 'designer'],
]);

map.forEach((v, k, map) => console.log(v)); // developer designer
map.forEach((v, k, map) => console.log(k)); // { name: 'Leo' } { name: 'Kim' }
map.forEach((v, k, map) => console.log(map));
/**
 * Map(2) {
  { name: 'Leo' } => 'developer',
  { name: 'Kim' } => 'designer'
}
Map(2) {
  { name: 'Leo' } => 'developer',
  { name: 'Kim' } => 'designer'
}
 */
// 
profile
오호
post-custom-banner

0개의 댓글