-
📊 Sort Without Articles 🎢Web/JS30 2020. 11. 19. 22:03반응형
Articles라고 함은, 'a', 'an', 'the'와 같은 관사를 의미한다.
보통 영화 제목같은 것들을 정렬할 때는, 관사를 빼고 정렬을 해야 올바른 정렬이 가능하기 때문에
(만약 관사를 빼지 않으면 거의 대부분의 영화 제목이 'The ~'로 인해 t에 정렬이 될 것이므로..)
이런 식으로 조건을 정해 놓은 정렬이 꼭 필요한 경우가 많다.
우리는 여러 밴드들의 이름을 가진 배열을 정렬해볼건데, 그 배열은 다음과 같다.
const bands = ['The Plot in You', 'The Devil Wears Prada', 'Pierce the Veil', 'Norma Jean', 'The Bled', 'Say Anything', 'The Midway State', 'We Came as Romans', 'Counterparts', 'Oh, Sleeper', 'A Skylit Drive', 'Anywhere But Here', 'An Old Dog'];
1. sort() 함수
우선, 자바스크립트에서 정렬은 sort() 함수를 이용하면 굉장히 편하게 구현할 수 있다.
someArray.sort((a, b) => some calculation);
sort() 함수의 콜백함수는 두 개의 인자를 받는데, 여기서는 편하게 a와 b로 칭하겠다.
a와 b는 각각 배열에서 두 개의 원소를 차례대로 뽑은 것을 의미한다.
만약 콜백함수가 0을 return하면 두 원소의 순서는 변하지 않는다.
양수를 return하면 a가 b보다 앞의 순서로, 즉 a, b 순으로 정렬이 되고
음수를 return하면 a가 b보다 뒤의 순서로, 즉 b, a 순으로 정렬이 된다.
이러한 사실을 이용해서, sort함수를 이용해 정렬하는 로직을 만들어보자.
const sortedBands = bands.sort((a, b) => { if(strip(a) > strip(b)) { return 1; } else { return -1; } });
한 가지 짚고 넘어가야 할 것은, sort를 숫자에만 사용할 수 있는 게 아니라는 사실이다.
문자열에 sort 함수를 사용하면, 알파벳 순으로 정렬을 할 수가 있다.
(사실 정확하게는 ASCII 코드 순서로 정렬되기 때문에 '123'과 '13'을 정렬하면 '13'이 더 크다거나, 그런 게 있지만..)
참고로 strip()이라는 함수는 아직 구현되지 않은, 밴드 이름에서 관사를 제거 하는 등의 가공을 하는 함수이다.
조금 있다가 살펴보기로 하고.
추가로, ternary operator와 implicit return 등을 이용하면 다음과 같이 한 줄로 줄이는 것도 가능.
const sortedBands = bands.sort((a, b) => strip(a) > strip(b) ? 1 : -1);
2. strip() 함수
근데 우리는 저 밴드 이름들을 그대로 정렬에 사용하기로 한 게 아니었다.
이름 맨 앞에 등장하는 관사들을 전부 제외하고 정렬하기로 했으므로,
'strip'이라는 이름의 함수를 통해 이를 구현해보자.
function strip(bandName) { return bandName.replace(/^(a |an |the )/i, '').trim(); }
문자열은 항상, 어떤 것을 구현하던 간에, 정규표현식을 사용하면 정말정말 간단해진다.
위의 정규표현식에서 '^'는 '맨 앞에'를 의미한다.
즉, ^(a |an |the )는 '맨 앞에 a, an, the 가 오는 애들을 찾아낸다'라는 의미.
그리고 맨 마지막에 i는 'insensitive'의 약자로, 대소문자를 구별하지 않는다는 의미이다.
즉, a, A, an, An, aN, AN 등을 모두 찾아내겠다는 의미.
참고로, 정규표현식에 띄어쓰기를 집어넣으면 그 띄어쓰기도 모두 반영되므로 주의하자.
맨 뒤에 'i'처럼 붙은 것을 'flag'라고 하는데, 이 flag들 중에 '띄어쓰기는 무시한다'라는 flag도 있다.
하지만, 이런 경우에는 띄어쓰기를 무시하면 대참사가 일어날 수 있기 때문에
('Anywhere' 같은 단어로 시작하는 경우까지 모두 찾아내서 'ywhere'가 되어버릴 수도 있다)
위의 정규표현식을 보면 'a ', 'an ', 'the '로, 뒤에 띄어쓰기를 집어넣은 모습을 볼 수 있다.
마지막에 trim()이 붙은 이유는, 가공 후에 공백이 생길 수도 있으니 혹시 모르는 경우를 대비.
(trim()은 앞뒤의 공백을 제거하는 역할)
이제 위에서 사용했던 strip() 함수를 구현했다.
참고로 strip() 함수는 if문 안에서만 사용이 되기 때문에, 원본 배열의 내용에는 아무런 영향도 끼치지 않는다.
3. 배열을 HTML로 집어넣기
이제, 위에서 정렬한 bandName 배열을 list로 만들어서 화면에 뿌릴 차례이다.
document.querySelector('#bands').innerHTML = sortedBands.map(band => `<li>${band}</li>`);
요렇게 화면에 뿌려보면, 다음과 같은 결과물이 화면에 뿌려지게 될 것이다.
왜 정렬된 항목들 사이에 콤마(,)가 껴서 귀찮게 하는 건지, 그 이유를 알아보자.
우리가 배열과 같이 String이 아닌 무언가를 innerHTML로 집어넣으려 할 경우,
DOM은 그 '무언가'의 toString() 메서드를 호출해서 문자열로 만든 후, 그것을 innerHTML에 사용하게 된다.
근데, 우리가 저 위의 map을 수행한 결과를 보면, 다음과 같은 배열일 것이다.
['<li>The Plot in You</li>', '<li>The Devil Wears Prada</li>', ...]
이런 식인데, 이 배열의 toString()을 호출하면 배열 내의 모든 원소를 콤마(,)를 이용하여 엮게 된다.
그래서, 그 결과물로 '모든 배열의 원소들이 콤마(,)로 연결된 문자열'이 탄생하게 되는 것이다.
console.log(sortedBands.toString());
밴드 이름들이 콤마를 기준으로 문자열로 합쳐졌다. 이런 참사를 막기 위해, 우리는 저 배열에다가 join 메서드를 사용해줘야 한다.
배열에다가 join('')를 사용하면 해당 배열의 모든 원소들을 아무런 문자 삽입 없이 연결시켜주기 때문에
우리가 원하는 결과물을 얻을 수 있게 된다.
document.querySelector('#bands').innerHTML = sortedBands.map(band => `<li>${band}</li>`).join('');
전체 자바스크립트 코드
<script> const bands = ['The Plot in You', 'The Devil Wears Prada', 'Pierce the Veil', 'Norma Jean', 'The Bled', 'Say Anything', 'The Midway State', 'We Came as Romans', 'Counterparts', 'Oh, Sleeper', 'A Skylit Drive', 'Anywhere But Here', 'An Old Dog']; function strip(bandName) { return bandName.replace(/^(a |an |the )/i, '').trim(); } const sortedBands = bands.sort((a, b) => { if(strip(a) > strip(b)) { return 1; } else { return -1; } }); console.log(sortedBands.toString()); document.querySelector('#bands').innerHTML = sortedBands.map(band => `<li>${band}</li>`).join(''); </script>
반응형'Web > JS30' 카테고리의 다른 글
🎤Native Speech Recognition📢 (0) 2020.11.23 ⌚Tally String Times with Reduce⏱ (0) 2020.11.20 🤩 CSS Text Shadow Mouse Move Effect 😎 (0) 2020.11.18 💿 LocalStorage & Event Delegation 📤 (0) 2020.11.17 🍴 References VS Copying 🎎 (0) 2020.11.13