[TIL]유사배열 공략ing

Violet Lee·2020년 10월 19일
0

javascript

목록 보기
17/24

오늘은 어떤 정보를 게시하기보다는, 풀기위해 시도했던 과정들을 한번 정리해보도록 하겠다.

문제는 다음과 같다.
Q) 문자열 중 숫자의 값의 합을, 숫자와 공백을 제외한 문자의 타입의 값의 개수로 나누어서 그 값을 정수로 반올림하라.

나는 이 문제를 보고, 먼저 저 문자열을 '유사배열'로 접근하는 방식을 생각했었다.

유사배열

  • document의 모든 tag들(node)
// NodeList [div, div, div, div, div, ...]
  • noscript등을 포함한 HTMLCollection들
  • 문자열
  • length속성을 지닌 객체

즉, 유사배열은 []으로 감싸져있지만 배열이 아닌 것들을 의미한다.
때문에 형태만 배열로 보일 뿐, array메소드들을 사용할 수 없다. 말 그대로 가짜배열이니까!

때문에 고차함수로 한글자씩 뜯어보면서 그 값의 진위여부를 판단하여 숫자값에 계속 더하고, 숫자나 공백 즉 숫자타입이 아닌 값들은 배열에 넣어서 그 길이를 판단할 수 있게!

... 내가 처음에 생각한 식은 이것이었다.

function numberSearch(str) {
  //문자열을 입력받아, 그 중 요소가 '숫자'인 것을 모두 찾는다.
  //그 요소들만 전부 더한후,그 값을 문자열 중 '숫자,공백이 아닌 요소들의 갯수'로 나눈 값을,
  //정수로 반올림하여 리턴해야 한다.

  //*빈 문자열을 입력받은 경우 0을 리턴해야한다.
  
  let onlyNum = 0;
  let ignoreNum = 0;
  if(str.length===0){
    return 0;
  }
  let newArr1 = [].filter.call(str, (function (i) { //얘가 숫자아닌거
    return (str[i]===null || str[i]===undefined);  
  }));
 
  let newArr2 = [].filter.call(str, (function (i) { //얘가 숫자.
    if(typeof Number(str[i]) === 'number'){
         return str[i];
    }
     
  }));
  for(let i=0;i<newArr2.length;i++){ //숫자인것 다 계산
    onlyNum = onlyNum  + Number(newArr2[i]);
  }
  for(let i=0;i<newArr1.length;i++){
    ignoreNum = ignoreNum + 1;
  }
  console.log(onlyNum);
  console.log(ignoreNum);
  return Math.floor(onlyNum/ignoreNum);
}

빈 배열 '[]'을 기준으로, call을 사용하여 유사배열에도 고차함수를 사용할 수 있게 하여, array 프로토타입 filter 를 가져와서 숫자값, 숫자가 아닌 값들을 골라낼 수 있게 하는게 처음 생각이었다.

코드리뷰
변수 newArr2에 들어가는 값들은 한 눈에도 뭐가 들어가는지 잘 보인다. 그러나, 숫자가 아닌 값들을 거르기 위해서 조건을 작성하는게 쉽지않았다. 😥😥

1차시도

let newArr1 = [].filter.call(str, (function (i) { //얘가 숫자아닌거
    return (!(typeof Number(str[i]) === 'number'));  
  //전혀 걸러지지 않고, 아예 이 if문을 건너뛰어버린다 ㅠㅠ
  }));

2차시도

let newArr1 = [].filter.call(str, (function (i) { //얘가 숫자아닌거
    return (str[i]===null || typeof str[i]=== NaN);  
  //코플릿에서 풀었잖아! NaN은 자기자신과도 비교할 수 없기때문에 정확한 계산이 필요해!!
  }));

3차시도

let newArr1 = [].filter.call(str, (function (i) { //얘가 숫자아닌거
    return (str[i]===null ||isNaN(Number(str[i])));  
   //isNaN을 그래서쓴건데 자꾸 undefined가 나오네..?
  //게다가, str[i]===null < 이 조건만 넣었을때도 안되서 
  //두 조건을 같이 거르든 하나만 넣든 어차피 안된다. 
  //json.parse()도 먹히지않았다. 
  //(여기서 뭔가 문제가 생겼다는걸 인지하지 못함.)
 
  }));

3차시도

let newArr1 = [].filter.call(str, (function (i) { //얘가 숫자아닌거
    return (str[i]===null ||str[i]===undefined);  
   //해서 그래, 니가 undefined를 뱉어낸다면, 그 타입이라는 거겠지. 니가 원하는대로 해줄께- 
  //해서 undefined로 쐐기를 박음. > 'hello6 '문자열 거르기 성공.
 
  }));

그러나 이상하게도 몇몇 문자열들은 걸러지지 않는것이었다. 똑같이 숫자 문자 공백을 섞은 문자열인데 몇개는 안 걸러지니 진이 빠졌다. 해서 레퍼런스를 확인했는데...
정확히는 거르는거에 집중하기보단, 이 엔지니어분도 뭔가 그런 부분을 많이 시행해보셨는지 비교의 접근으로 작성해주셨다.

  let digits = '0123456789'; //미리 비교할 문자열 타입 수를 하나 선언
 if(str===''){
     return 0;
 }
 let sum=0;
 let pureStr = '';
 for(let i=0;i<str.length;i++){
     if(digits.includes(str[i])){ //str의 i번째 문자열형 숫자 중 숫자데이터가 하나라도 있으면
         sum = sum+Number(str[i]); //넘버형으로 바꿔서 sum에 더하기.
     }else if(str[i]!==' '){ //string형 숫자데이터가 '아닌'것중에서, '공백'도 아닌것 거르기. 
         pureStr += str[i]
     }
 }
     return Math.round(sum/pureStr.length); //MAth.round()로 소수점 이하를 반올림한다.

filter가 걸러주지 못했던 이유가 뭔지 안타깝게도 아직 찾지못했다. 분명하게 '!'연산자를 썼는지 거르지 못한 이유는 ? 뭘까..?

profile
예비개발자

0개의 댓글