https://school.programmers.co.kr/learn/courses/30/lessons/42893
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
정규식을 적극적으로 활용해서 문제를 풀었다.
평소에 문자열 다루는걸 싫어해서 피해왔는데, 이정도로 문자열을 다루기는 처음인 것 같다.
javascript의 정규식을 이용해서 비교적 간단하게 풀었지만, 만약 c나 c++이나 c#으로 풀었다면 어떻게 했을지 상상만 해도 끔찍하다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
RegExp - JavaScript | MDN
There are two ways to create a RegExp object: a literal notation and a constructor. The literal notation takes a pattern between two slashes, followed by optional flags, after the second slash. The constructor function takes either a string or a RegExp obj
developer.mozilla.org
정규식과 관련해서는 공식 문서와 GEMINI를 통해서 공부했다.
Regex의 match 메서드와 matchAll 메서드 사용법을 배웠다.
match 메서드는 정규식에 g 플래그가 쓰였는지에 따라 반환값이 달라진다. 만약 정규식에 g 플래그를 사용했다면 정규식에 해당하는 전체 표현이 반환되고, 캡쳐링 그룹은 포함되지 않는다. 만약 정규식에 g 플래그를 사용하지 않았다면 정규식에 해당하는 전체 표현과 캡쳐링 그룹이 반환된다. 이 경우 exec와 같은 반환값을 가진다.
match 메서드만을 가지고는 모든 캡쳐링 그룹을 찾을 수 없으므로 matchAll 메서드를 사용해야한다.
matchAll 메서드는 마치 exec가 null을 반환할때까지 반복 수행하는것과 같은 반환값을 가진다. matchAll의 반환값은 iterable iterator object형태를 가진다. 이 값은 그대로 쓸 수는 없지만 이 값을 순회하면 마치 exec를 수행한 것과 같은 값을 가질 수 있다.
// 두가지 방식으로 호출할 수 있다.
let matchs = "abcabcdabcde".matchAll(/a/g);
let matchs2 = /a/g[Symbol.matchAll]("abc");
// matchAll의 결과인 matchs를 순회하여 사용할 수 있다.
for(var match of matchs){
// match는 Symbol.exec(/a/g)의 결과와 같다.
console.log(match[0]); // "a"
console.log(match[1]); // 만약 캡쳐링 그룹이 있다면 첫번째 캡쳐링 그룹을 출력한다.
console.log(match[2]); // 만약 캡쳐링 그룹이 있다면 두번째 캡쳐링 그룹을 출력한다.
console.log(match[index]); // 0
console.log(match[input]); // "abcabcdabcde"
}
아직 exec를 제대로 써보지 못해서 어색하지만, 여러번 쓰다보면 익숙해질 것이다.
코드
function solution(word, pages) {
var answer = 0;
// pages에서 객체 구성
// 각 요소는 page_idx : [page_url, base_score, #link, link_score]
var page_info = {};
for (var i = 0; i < pages.length; i++) {
var page = pages[i];
// 페이지에서 기본 데이터 추출 (page_idx : [page_url, base_score, #link, link_score])
var page_url = "";
var base_score = 0;
// url 추출
let regex = /<meta property="og:url" content="([^"]*)"/;
let match = page.match(regex);
if (match && match[1]) {
page_url = match[1];
}
// 기본 점수 추출
regex = new RegExp(`(?<![a-z])${word}(?![a-z])`, 'gi');
match = page.match(regex);
base_score = match ? match.length : 0;
page_info[i] = [page_url, base_score, 0, 0]
}
for (var i = 0; i < pages.length; i++) {
var page = pages[i];
var page_url = page_info[i][0];
var base_score = page_info[i][1];
// 링크 갯수 추출
var link_count = 0;
var regex = /<a href="([^"]*)"/g;
var match = Array.from(page.matchAll(regex), (x) => x[1]);
link_count = match ? match.length : 0;
page_info[i][2] = link_count;
// 링크 점수계산
for (var link of match) {
for (var j = 0; j < Object.keys(page_info).length; j++) {
if (page_info[j][0] === link) {
page_info[j][3] += base_score / link_count;
break;
}
}
}
}
// 결과 반환
for (var i = 0; i < Object.keys(page_info).length; i++) {
if (page_info[i][1] + page_info[i][3] > page_info[answer][1] + page_info[answer][3]) answer = i;
}
return answer;
}'코딩연습' 카테고리의 다른 글
| (C#) 지형 편집 (0) | 2025.09.17 |
|---|---|
| (C#) 등산코스 정하기 (0) | 2025.09.17 |
| (javascript) 경주로 건설 (0) | 2025.09.12 |
| (javascript) 외벽 점검 (0) | 2025.09.11 |
| (javascript) 행렬과 연산 (6) | 2025.08.07 |