inArray

Codewars 문제 풀이

inArray 문제

문자열 a1과 a2의 두 배열이 주어지면 문자열 a1는 a2의 하위 문자열인 문자열 사전순으로 정렬된 배열 r을 반환합니다.

Example 1:

  • a1 = ["arp", "live", "strong"]
    a2 = ["lively", "alive", "harp", "sharp", "armstrong"]
    returns ["arp", "live", "strong"]

Example 2:

  • a1 = ["tarp", "mice", "bull"]
    a2 = ["lively", "alive", "harp", "sharp", "armstrong"]
    returns []

주의:

  • Shell bash a1 및 a2에는 문자열이 있습니다. 반환은 단어가 쉼표로 구분되는 문자열입니다.
  • r에는 중복 항목이 없어야 합니다.

나의 풀이

function inArray(arr1, arr2) {
  const result = [];
  arr1.forEach((a1) => {
    arr2.forEach((a2) => {
      if (a2.includes(a1)) result.push(a1);
    });
  });

  return result
    .reduce((a, c) => {
      if (!a.includes(c)) a.push(c);
      return a;
    }, [])
    .sort();
}
  1. 조건에 만족하는 배열을 담을 result 변수를 선언하고 빈 배열을 할당했다.
  2. arr1arr2 둘 다 모든 요소를 순회하며 비교 후 조건에 맞는지 확인해야 한다. 그 때문에 배열의 forEach()메서드를 중첩 사용했다.

원래는 forEach()대신 filter()를 중첩 사용해 바로 반환하려고 했다. 하지만 다음과 같이 코드를 작성하면 반환 값은 a2.includes(a1)true로 평가된 값들이 아닌 arr1이 그대로 나왔고, 그 이유를 알 수 없어 forEach()로 대체했다.

function inArray(arr1, arr2) {
  return arr1.filter((a1) => {
    return arr2.filter((a2) => {
      return a2.includes(a1);
    });
  });
}
//return arr1

왜 arr1이 그대로 반환됐을까?
filter()메서드는 콜백함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다.
위 함수를 뜯어보면 내부 filter메서드에는 a2.includes(a1)가 실행되며 true값 평가가 이뤄지고 true인 해당 값을 내부 filter()메서드의 값으로 반환한다.
하지만 외부 filter메서드는 true로 평가될 기준이 없다. return 뒤에는 내부 filter메서드가 반환한 문자열 값만 있을 뿐이다.
문자열 데이터는 filter메서드에서 강제 true로 평가된다. 즉, 순회 중인 a1가 무슨 값이든 true로 인정되고 따라서 arr1이 그대로 반환된 것이다.
만약 외부 filter에 내부 고차함수를 사용하고 싶다면, 내부 고차함수가 true, false로 평가되는 some(), every()메서드를 사용하자!

  1. arr2 요소의 하위 문자열로 arr1 문자가 있는지 확인작업이 필요하다. 이때, 외부 forEach에 돌고 있는 a1과 내부 forEach를 돌고 있는 a2 둘 다 문자열이다. 따라서 string.prototype.includes()메서드를 사용해 인수로 전달받은 a1문자열이 a2문자열에 있는지 확인할 수 있다. 만약 있다면 true로 조건이 평가되어 result 변숫값인 배열에 해당 요소를 push한다.
  2. forEach()메서드가 끝나면 result를 바로 반환하지 않는다. 왜냐하면 result 배열에 요소의 중복을 허용하지 않는다는 주의사항이 있기 때문이다.
  3. reduce()메서드를 사용해 초깃값을 빈 배열로 설정한다. 그리고 만약 빈 배열에 해당 요소가 없다면 push한다.
  4. 마지막으로 알파벳 정렬을 위해 유니코드 순서로 정렬하는 배열의 메서드 sort()를 사용 후 반환한다.

다른 사람 풀이

OverZealous (plus 11 more warriors)

function inArray(arr1, arr2) {
  return arr1.filter(function(needle) {
    return arr2.some(function(haystack) {
      return haystack.indexOf(needle) > -1;
    });
  }).sort();
}
  1. 외부에는 arr1filter메서드 사용하면서 true인 요소를 반환한다.
  2. 순회 중인 arr1의 요소 needletrue인지 평가하는 기준은 arr2some메서드를 사용해 반환되는 값이다.
  3. 순회 중인 arr2의 요소 hasystack문자열은 arr1의 요소 needle문자열을 포함하고 있다면 indexOf메서드 평가에 의해 해당 인덱스를 반하는데 이때, 인덱스 값은 -1보다 반드시 크다. 때문에 some()메서드는 true로 평가한다.
    만약 없다면 실패로 -1을 반환한다. 이 값은 조건에 충족하지 못하기 때문에 some()메서드는 해당 요소를 false로 평가한다.
  4. some()메서드에서 true로 평가된 요소는 외부 filter() 메서드의 반환 값이 된다.
  5. 함수 inArray는 최종적으로 filter 메서드의 반환 값들에 sort()메서드를 적용 후 정렬된 값을 반환한다.

좋은 웹페이지 즐겨찾기