이전 포스팅에서는 Key, Value로 이루어진 맵(Map)이라는 자료 구조형을 알아보았다. 유용한 Property 및 메소드 등을 활용하여 유용하게 쓰이는 자료구조였지만 맵은 중복 값을 허용한다. 이를테면 아래와 같다.
let map = new Map();
map.set('s', 1);
map.set('s', 2);
map.set('r', 3);
console.log(map)
// Result
// s : 2
// r : 3
위의 코드를 보면 알 수 있듯이, set함수를 통해 's'라는 동일한 키 값으로 저장할 경우 이전 데이터를 엎어 쓰게 된다. 이를 방지하려면 set을 하기전, has()함수를 통해 값이 있는지를 확인하고 저장해야 하는 번거로움이 있다.
Map 뿐만 아니라, 다른 상황에서도 마찬가지 이다. 아래의 코드를 살펴보자.
let sample = ['a to b', 'b to c', 'c to a', 'a to c', 'b to c'];
// 중복값 여부 확인 (중복 없을 경우 undefined)
let dup = sample.find(s => s === 'b to c');
// 중복값 제거하기
const uniqueArr = sample.filter((element, index) => {
return sample.indexOf(element) === index;
});
console.log(uniqueArr); // ['a to b', 'b to c', 'c to a', 'a to c']
위의 코드처럼 중복 값을 찾거나 중복 값을 제거하려면 번거로운 작업을 거쳐야 한다. 이를 조금 더 간편하게 할 수 있는 방법이 셋(Set)을 활용하는 것이다.
셋(Set)
셋은 중복 값이 없는 Collection이다. 셋에는 Key가 없이 Value가 저장된다. Map과 같이 Set에서도 활용할 수 있는 메서드와 Property들이 있다.
Set의 메서드
- new Set(iterable)
Set을 Initialize한다. Iterable 객체를 전달 받으면, 그 안의 값을 복사해 Set에 넣어준다. 이 과정에 중복된 것은 제거된다. - set.add(value)
Value를 추가하고 Set 자신을 반환한다. 이때 동일한 Value가 있다면 아무리 많이 호출해도 추가되지 않는다. - set.delete(value)
Value를 제거한다. Value가 있어 제거를 하면 true, 아니라면 false를 반환한다. - set.has(value)
Set내에 Value가 존재하면 true, 아니면 false를 반환한다. - set.clear()
Set에 있는 값을 비운다. - set.size
Set의 value 갯수를 반환한다. - set.keys()
Set 내의 모든 Value를 포함하는 Iterable 객채를 반환한다. - set.values()
set.keys()와 동일한 작업을 하며, Map과의 호환성을 위해 만들어진 메서드이다. - set.entries()
Set내의 값을 이용해 만든 [value, value] 배열을 보함하는 Iterable 객체를 반환한다. Map과의 호환성을 위해 만들어졌다.
티스토리의 방문자 수를 늘리기 위해, 동일한 사용자가 아무리 많이 접속해도 1건 이상으로 처리하지 않는다. 이러한 구현을 간단하게 하고자 Set을 활용하려고 한다. 아래의 코드를 통해 방법을 알아보자.
let set = new Set();
let user1 = { ip: '111.111.111.1'}
let user2 = { ip: '111.111.111.2'}
let user3 = { ip: '111.111.111.3'}
// 방문자가 접속 시, add 메서드를 통해 set에 추가한다.
// 동일 방문자가 여러 번 접속할 수 있다.
set.add(user1);
set.add(user2);
set.add(user3);
set.add(user1);
set.add(user1);
// Set에는 중복값이 저장되지 않으므로 size 즉, 방문자 수는 3이다.
console.log(set.size); // 3
for(let visitor of set) {
console.log(visitor.ip)
// 111.111.111.1, 111.111.111.2, 111.111.111.3
}
Set 대신, 배열을 사용해서, 중복 값 여부를 위의 방법과 같이 확인하여 저장한다던지 전부 저장하고나서 중복 제거를 통해 방문자 수를 표시한다던지의 대안을 고려할 수 있지만, Set보다는 성능면에서 떨어진다. (배열 내요소 전체를 뒤져 중복값을 찾기 때문에) Set은 중복값을 확인하는데 최적화 되어 있다.
Set의 Value를 반복하기
for..of나 forEach를 통해 Set의 값을 대상으로 반복문 작업을 수행할 수 있다.
let set = new Set(['soopiri', '수피리', 'hi']);
// for..of
for (let value of set) {
console.log(value);
}
// forEach
set.forEach((value, value2, set) => {
console.log(value);
});
위의 코드에서 forEach문은 3개의 파라미터를 받는다. value와 value2는 같은 값인데 왜 두번 스인 것일까? 이유는 바로 Map과의 호환성 때문이다. 이렇게 구현된 덕분에 Map to Set, Set to Map으로 교체하기가 쉬워진다.
마무리
Set은 중복을 허용하지 않는 Collection이며, Key 없이 Value만 저장이 된다. Map과 유사하게 구현이 되어 있어 Map과의 호환성이 좋다. Map과 Set은 추가한 순서대로 저장이 되지만, Collection 내의 값들을 재 정렬하거나, 숫자를 이용해서 특정 값을 가지고 오는 것은 불가능 하다.
참고자료
'Development > JavaScript' 카테고리의 다른 글
defer와 async란? (0) | 2022.05.11 |
---|---|
Javascript - 원시값(Primitive)의 메서드 (0) | 2022.04.27 |
Javascript - 맵(Map)을 알아보자 (0) | 2022.04.27 |
구조 분해 할당(Destructuring Assignment) - 객체, 중첩구조 편 (0) | 2022.04.26 |
구조 분해 할당(Destructuring Assignment) - 배열편 (0) | 2022.04.25 |