
적절한 메서드가 있음에도 나는 또 반복문을 남발해버렸다.
그리고 Map 자료구조에 익숙치 않아 결국 문제를 틀려버렸다.
내가 풀었던 문제는 다음과 같다.
문제: 애너그램 걸러내기
애너그램(어구전철)은 단어나 문장을 구성하고 있는 문자의 순서를 바꾸어 다른 단어나 문장을 만드는 놀이입니다.
예시:
nap - pan
ear - are - era
cheaters - hectares - teachers
애너그램으로 만든 단어를 걸러내는 함수 aclean(arr)을 만들어보세요.
예시:
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) ); // "nap,teachers,ear"나 "PAN,cheaters,era"이 출력되어야 합니다.
애너그램 그룹에서 한 단어는 남아있어야 합니다.
공식 답안
function aclean(arr) {
let map = new Map();
for (let word of arr) {
// 단어를 글자 단위로 쪼갠 후, 알파벳 순으로 정렬한 다음에 다시 합칩니다.
let sorted = word.toLowerCase().split('').sort().join(''); // (*)
map.set(sorted, word);
}
return Array.from(map.values());
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) );
내가 쓴 답안(틀림)
function aclean(words) {
//1. 모두 소문자로 만들어주기
let lowerCaseArr = [];
for(let word of words) {
lowerCaseArr.push(word.toLowerCase());
}
//2. 'nap'을 [n, a, p]로 만들어준다. 그리고 그 배열들이 모인 새로운 배열을 만든다.
let wordToCharArr = lowerCaseArr.map(item => {
let tempArr = [];
for(let char of item){
tempArr.push(char);
}
return tempArr;
});
//3. 각 요소 (ex: ['n', 'a', 'p'])를 정렬해준다.
for(let i = 0; i < wordToCharArr.length; i++){
wordToCharArr[i].sort();
}
//4. ['a', 'n', 'p']의 각 요소를 붙여서 한 단어로 만들어준다.
let charToWordArr = wordToCharArr.map(charArr => {
let word = '';
for(let char of charArr){
word += char;
}
return word;
});
//5. Set을 만드는데 iterable 객체를 넣어준다.
let resultSet = Array.from(new Set( charToWordArr));
return resultSet;
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
console.log(aclean(arr));
내 코드에는 다음과 같은 문제가 있다.
- Set 자료구조를 사용해 중복성은 제거했으나, 단어의 원형을 출력해내진 못했다.
- 잦은 for문으로 코드가 복잡하다.
나는 다음과 같이 정리하려고 한다.
map
자료구조에 익숙치 않아 틀렸기에,map
의 개념 정리하기for
문 대신 쓸 수 있었던split
과join
메서드 개념 정리- 추가로
Array.from()
정리 - 공식 답안 분석
맵(Map)
맵(Map)은 키가 있는 데이터를 저장한다는 점에서 객체와 유사하지만, 맵은 키에 다양한 자료형을 허용한다는 점에서 차이가 있다.
맵의 주요 메서드 및 프로퍼티
new Map()
– 맵을 만든다map.set(key, value)
– key를 이용해 value를 저장한다.map.get(key)
– key에 해당하는 값을 반환한다. key가 존재하지 않으면 undefined를 반환한다.map.has(key)
– key가 존재하면 true, 존재하지 않으면 false를 반환.map.delete(key)
– key에 해당하는 값을 삭제.map.clear()
– 맵 안의 모든 요소를 제거.map.size
– 요소의 개수를 반환.
⭐맵의 가장 중요한 기능: 맵은 키로 객체를 허용한다.
예시:
let john = { name: "John" };
// 고객의 가게 방문 횟수를 세본다고 가정해 봅시다.
let visitsCountMap = new Map();
// john을 맵의 키로 사용하겠습니다.
visitsCountMap.set(john, 123);
alert( visitsCountMap.get(john) ); // 123
ℹ️체이닝
map.set
을 호출할 때마다 맵 자신이 반환된다. 이를 이용하면 map.set
을 '체이닝(chaining)'할 수 있다.
map.set('1', 'str1')
.set(1, 'num1')
.set(true, 'bool1');
맵의 요소에 반복 작업하기
다음 세 가지 메서드를 이용해 맵의 각 요소에 반복 작업 할 수 있다.
map.keys()
- 각 요소의 키를 모은 반복 가능한(iterable, 이터러블) 객체를 반환한다.map.values()
- 각 요소의 값을 모은 이터러블 객체를 반환한다.map.entries()
- 요소의 [키, 값]을 한 쌍으로 하는 이터러블 객체를 반환한다. 이 이터러블 객체는for..of
반복문의 기초로 쓰인다.
예시:
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// 키(vegetable)를 대상으로 순회합니다.
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
// 값(amount)을 대상으로 순회합니다.
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
// [키, 값] 쌍을 대상으로 순회합니다.
for (let entry of recipeMap) { // recipeMap.entries()와 동일합니다.
alert(entry); // cucumber,500 ...
}
그 외 정보는 링크에서 확인: https://ko.javascript.info/map-set#ref-773
split과 join
str.split(delim)
str.split(delim) 메서드는 구분자(delimiter) delim을 기준으로 문자열을 쪼갠다.
예시:
let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');
for (let name of arr) {
alert( `${name}에게 보내는 메시지` ); // Bilbo에게 보내는 메시지
}
ℹ️문자열을 글자 단위로 분리하기
split(s)
의 s를 빈 문자열로 지정하면 문자열을 글자 단위로 분리할 수 있다.
let str = "test";
alert( str.split('') ); // t,e,s,t
arr.join(glue)
arr.join(glue) 메서드는 인수 glue를 접착제처럼 사용해 배열 요소를 모두 합친 후 하나의 문자열을 만들어준다.
예시:
let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
let str = arr.join(';'); // 배열 요소 모두를 ;를 사용해 하나의 문자열로 합칩니다.
alert( str ); // Bilbo;Gandalf;Nazgul
Array.from()
범용 메서드 Array.from()은 이터러블이나 유사 배열을 받아 '진짜' Array로 만들어준다.
예시:
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
let arr = Array.from(arrayLike); // (*)
alert(arr.pop()); // World (메서드가 제대로 동작합니다.)
(*)
로 표시한 줄에 있는 Array.from
은 객체를 받아 이터러블이나 유사 배열인지 조사합니다. 넘겨 받은 인수가 이터러블이나 유사 배열인 경우, 새로운 배열을 만들고 객체의 모든 요소를 새롭게 만든 배열로 복사합니다.
공식 답안 분석
자 이제 위에서 공부한 개념으로 공식 답안을 분석해보자.
공식 답안
function aclean(arr) {
let map = new Map();
for (let word of arr) {
// 단어를 글자 단위로 쪼갠 후, 알파벳 순으로 정렬한 다음에 다시 합칩니다.
let sorted = word.toLowerCase().split('').sort().join(''); // (*)
map.set(sorted, word);
}
return Array.from(map.values());
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) );
분석
(*) 로 표시한 줄을 여러 줄에 나눠서 작성하면 아래와 같은 코드가 된다.
let sorted = word // PAN
.toLowerCase() // pan
.split('') // ['p','a','n']
.sort() // ['a','n','p']
.join(''); // anp
str.split('')
을 사용하면 문자열을 글자 단위로 분리할 수 있고,str.split('')
의 결과는 배열이 된다. 그래서 뒤에 배열 메서드인.sort()
를 사용할 수 있는 것이다.arr.join('')
을 사용하여 배열 요소를 모두 합친 후 하나의 문자열을 만들어줬다.
아래 코드는 단어를 맵에 저장한다.
map.set(sorted, word);
정렬 이후의 글자 구성이 같은 단어를 또다시 만나게 되면, 키가 동일하므로 값이 덮어씌워진다. 따라서 맵엔 글자 구성이 같은 단어는 단 한 번만 저장됩니다.
return Array.from(map.values());
map.values()
는 각 요소의 값을 모은 이터러블 객체를 반환한다.Array.from()
은 이터러블 객체를 배열로 바꿔준다.
추가 참고
반복 가능한(iterable, 이터러블) 객체
- 배열을 일반화한 객체이다.
- 메서드
Symbol.iterator
가 구현된 객체이다.
더 자세한 내용은 링크 참고: https://ko.javascript.info/iterable
앞으로 메서드를 잘 사용하길 바라며 글을 여기서 마친다!
반복문! 이제 그만!

'Programming Language > JavaScript' 카테고리의 다른 글
[JavaScript] setTimeout은 현재 실행 중인 스크립트의 처리가 종료된 이후에 실행된다! (0) | 2022.12.23 |
---|---|
[JavaScript] Object.entries(obj)가 반환하는 건 맵이 아닌 '배열'이다! (0) | 2022.11.19 |
[Javascript] 반복문 lover인 나에게 map과 reduce를 건네본다..❤️ (0) | 2022.11.16 |
[Javascript] 대괄호 표기법으로 프로퍼티 값 읽을 때 주의하자! (0) | 2022.11.15 |