[알고리즘] 고차함수

HIHI JIN·2023년 1월 12일

알고리즘

목록 보기
5/29
post-thumbnail

코드스테이츠 코플릿(알고리즘) 문제 - 고차함수 편

<고차함수 기본>

  1. 'Hello HoF!' 리턴하는 함수를 리턴해야 합니다.
function returnFunction() {
  return function (){
  return 'Hello HoF!';
}
}
  1. 함수와 수(num)를 입력받아 num에 함수를 적용(apply)한 결과를 리턴해야 합니다.
    입력받은 함수가 어떤 일을 하는지는 중요하지 않습니다.
function functionParameter(func, num) {
  return func(num);
}
  1. 함수와 수(num)를 입력받아 num에 함수를 두 번(twice) 적용(apply)한 결과를 리턴해야 합니다. 입력받은 함수가 어떤 일을 하는지는 중요하지 않습니다.
function applyTwice(func, num) {
  return func(func(num));
}
  1. 두 개의 함수와 수(num)를 입력받아 num에 함수들을 num에 가까운 순서대로 적용한 결과를 리턴해야 합니다. 입력받은 함수가 어떤 일을 하는지는 중요하지 않습니다.
function compose(func1, func2, num) {
  return func1(func2(num));
}
  1. 두 개의 함수를 입력받아 두 함수가 결합된 새로운 함수를 리턴해야 합니다.
    입력받은 함수가 어떤 일을 하는지는 중요하지 않습니다.
function compose2(func1, func2) {
  return function (num) {
    return func1(func2(num));
  };
}
//num을 인자로 받는 fun2의 결과가 다시 인자가 되어 인자로 func1의 결과가 리턴
  1. 함수들을 입력받아 함수들이 입력된 차례대로 결합된 새로운 함수를 리턴해야 합니다.
    입력되는 함수들의 수는 1개 이상이라고 가정합니다.
    입력받은 함수가 어떤 일을 하는지는 중요하지 않습니다.
function pipe(...funcs) {
  return function (num) {
    for (let i = 0; i < funcs.length; i++) {
      num = funcs[i](num);
    }
    return num;
  };
}
//...funcs 스프레드 문법
//인자로 받는 많은 function들(콜백함수)을 배열로 하나로 묶어 그 배열의 이름이 ...funcs이다.
  1. 함수와 객체를 입력받아 조건별로 아래와 같은 동작을 수행해야 합니다.
    객체의 'status' 속성값이 'fail'인 경우, 'Something went wrong!'을 리턴해야 합니다.
    객체의 'status' 속성값이 'success'인 경우, 'data' 속성값에 입력받은 함수를 적용한 결과를 리턴해야 합니다.
function callbackOnly(callback, response) {
  if(response.status === 'success'){
    return callback(response.data);
  }else if(response.status === 'fail'){
    return 'Something went wrong!';
  }
}
  1. 함수와 배열을 입력받아 배열의 각 요소에 함수가 적용된 새로운 배열을 리턴해야 합니다.
    반복문(for)문을 사용해야 합니다.
    arr.map 사용은 금지됩니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
function mapCallback(func, arr) {
  let newArr = [];
  for(let i of arr){
    newArr.push(func(i));
  }
  return newArr;
}
  1. 함수와 배열을 입력받아 배열의 각 요소에 함수를 적용했을 때 그 결과가 참인 요소만을 갖는 새로운 배열을 리턴해야 합니다.
    반복문(for)문을 사용해야 합니다.
    arr.filter 사용은 금지됩니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
function filterCallback(func, arr) {
  let newArr = [];
  for(let i of arr){
    if(func(i)===true){
      newArr.push(i);
    }
  }
  return newArr;
}

<내장 고차함수 메서드 : Filter, Map, Reduce>

  1. 배열과 임의의 값(discarder)을 입력받아 기존 배열에서 discarder와 일치하는 요소가 제거된 새로운 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    arr.indexOf, arr.splice, arr.slice, arr.forEach 등의 사용은 금지됩니다.
    반드시 arr.filter를 이용해서 풀어야 합니다.
    입력받은 배열을 수정하지 않아야 합니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
function removeElement(arr, discarder) {
  return arr.filter(v => v !== discarder);
}
  1. 배열과 임의의 값(keeper)을 입력받아 기존 배열에서 keeper와 일치하는 요소만을 갖는 새로운 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    arr.indexOf, arr.splice, arr.slice, arr.forEach 등의 사용은 금지됩니다.
    반드시 arr.filter를 이용해서 풀어야 합니다.
    입력받은 배열을 수정하지 않아야 합니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
    keeper와 일치하는 요소가 없는 경우, 빈 배열을 리턴해야 합니다.
function keep(arr, keeper) {
  return arr.filter(v => v === keeper);
}
  1. 문자열을 요소로 갖는 배열을 입력받아 그 길이가 홀수인 요소만을 갖는 배열을 리턴해야 합니다. 반복문(for, while) 사용은 금지됩니다.
    arr.indexOf, arr.splice, arr.slice, arr.forEach 등의 사용은 금지됩니다.
    반드시 arr.filter를 이용해서 풀어야 합니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
function filterOddLengthWords(words) {
  return words.filter(v => v.length % 2 === 1);
}
  1. 정수를 요소로 갖는 배열과 정수(num)를 입력받아 num을 배열에 추가하고 정렬한다고 가정할 경우, num의 인덱스를 리턴해야 합니다.(어려움 ⭐⭐⭐⭐⭐)
    반복문(for, while) 사용은 금지됩니다.
    arr.sort, arr.indexOf 사용은 금지됩니다.
    빈 배열을 입력받은 경우, 0을 리턴해야 합니다.
    num은 arr의 어떤 요소와도 같지 않다고 가정합니다.
function getIndex(arr, num) {
  return arr.filter(v=> v<num).length;
}
//[5,4,3,1]배열이 있다면 num이 들어가고 num=2라면
//[1,2,3,4,5]로 정렬 후 num의 인덱스 1을 리턴
//num보다 작은거만 배열에 넣고, 배열의 length를 출력하면 num이 들어올자리의 인덱스가 구해짐
  1. 객체와 키를 입력받아 키에 해당하는 값이 배열인 경우, 100 보다 작은 요소들만 갖는 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    대소 비교는 number 타입에만 적용합니다.
    주어진 키에 해당하는 값이 배열이고, 100 미만인 요소가 있는 경우에만 해당 요소를 갖는 배열을 리턴해야 합니다.
    그 외의 경우, 빈 배열을 리턴해야 합니다.
    주어진 보조 함수(lessThan100)를 사용해야 합니다.
function lessThan100(number) {
  return number < 100;
}

function getElementsLessThan100AtProperty(obj, property) {
  if(Array.isArray(obj[property])){
    return obj[property].filter(v => typeof(v)==='number' && lessThan100(v));
  }else{
    return [];
  }
}
//obj[property]가 배열이라면 Array.isArray()===true
//그 배열이 100보다 작은 요소들만 갖는다면 리턴
//배열의 요소들이 숫자인 경우에만 true
  1. 수를 요소로 갖는 배열을 입력받아 각 요소를 2배 곱한 새로운 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    반드시 arr.map를 이용해서 풀어야 합니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
function getDoubledElements(arr) {
  return arr.map(v => v*2);
}
  1. 문자열을 요소로 갖는 배열을 입력받아 각 요소의 길이를 요소로 갖는 새로운 배열을 리턴해야 합니다. 반복문(for, while) 사용은 금지됩니다.
    반드시 arr.map를 이용해서 풀어야 합니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
function getLengthOfElements(arr) {
  return arr.map(v=>v.length);
}
  1. 수를 요소로 갖는 배열을 입력받아 각 요소가 2의 배수인지에 대한 정보를 요소로 갖는 새로운 배열을 리턴해야 합니다.
    arr[i]이 2의 배수일 경우, 새로운 배열의 i번째 요소는 'ok'
    arr[i]이 2의 배수가 아닐 경우, 새로운 배열의 i번째 요소는 'no'
    반복문(for, while) 사용은 금지됩니다.
    반드시 arr.map를 이용해서 풀어야 합니다.
    빈 배열을 입력받은 경우, 빈 배열을 리턴해야 합니다.
    0은 2의 배수가 아니라고 가정합니다.
function checkEvenOrNot(arr) {
  return arr.map(v => v===0 || v%2!==0 ? 'no':'ok');
}
  1. 개인 정보를 담고 있는 객체를 요소로 갖는 배열을 입력받아 각 객체의 'name' 속성을 요소로 갖는 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    빈 배열이 주어진 경우에는 빈 배열을 리턴해야 합니다.
function getOnlyNames(arr) {
  return arr.map(v=> v.name);
  //배열 arr의 객체요소들에서 객체.name만 꺼내서 arr에 객체 <=>객체.name 바꿔넣기
}
//arr은 객체를 요소 갖는 배열
//객체는 개인정보들
//배열에서 각 객체의 name값을 가져와서 새로운 배열에 넣기
  1. 개인 정보를 담고 있는 객체를 요소로 갖는 배열을 입력받아 이름 전체를 요소로 갖는 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    이름 전체는 'firstName', 'lastName' 속성값 사이에 띄어쓰기 하나를 둔 문자열입니다.
    'firstName', 'lastName' 속성값 사이에 띄어쓰기 하나를 추가해야 합니다.
    빈 배열이 주어진 경우에는 빈 배열을 리턴해야 합니다.
function getFullNames(arr) {
  return arr.map(v => v.firstName +" "+ v.lastName);
}
//arr 객체를 요소로 갖음
//이름만 빼기
  1. 객체와 키를 입력받아 키에 해당하는 값이 배열인 경우, 배열의 각 요소를 제곱한 새로운 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    주어진 키에 해당하는 값이 배열인 경우, 해당 배열은 number 타입의 정수만을 요소로 갖는다고 가정합니다.
    주어진 보조 함수(square)를 사용해야 합니다.
function square(number) {
  return number * number;
}

function getSquaredElementsAtProperty(obj, property) {
  if(Array.isArray(obj[property])){
    return obj[property].map(v => square(v));
  }
  return [];

}
//obj[property]가 배열이라면, 배열의 각 요소v를 square(v)값으로 바꾸기
//obj[property].map(v => square(v))
  1. 개인 정보를 담고 있는 객체를 요소로 갖는 배열을 입력받아 18세 이상인 사람의 이름을 요소로 갖는 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    빈 배열이 주어진 경우에는 빈 배열을 리턴해야 합니다.
function getOnlyAllowedToDrink(arr) {
  return arr.filter(v => v.age>=18).map(v => v.name);
}
//객체가 요소인 arr
//18세이상인 객체만 남기기
//그 객체의 이름만 남기기
//newArr = arr.filter(v => v.age>=18)
//newArr.map(v => v.name)
  1. 영화 정보가 담긴 객체를 요소로 갖는 배열과 연도를 입력받아 해당 연도 이전의 영화를 요소로 갖는 배열을 리턴해야 합니다.
    string 타입을 요소로 갖는 배열을 리턴해야 합니다.
    각 요소는 영화 제목 by 영화 감독의 형태를 가져야 합니다.
function classicMovies(arr, year) {
  return arr.filter(v => v.year<year).map(v => `${v.title} by ${v.director}`);
}
//영화정보가 담긴 객체가 요소인 arr
//year이전의 영화만 요소로 갖는다.
//map인데 조건을 추가한
//return arr.filter(v => v.year<year).map(v => `${title} by ${director}`);
  1. number 타입을 요소로 갖는 배열을 입력받아 배열의 모든 요소의 합을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    반드시 arr.reduce를 이용해서 풀어야 합니다.
function computeSumOfAllElements(arr) {
  return arr.reduce((acc,cur) => {return acc+cur},0);
}
//누적합을 구할 때는 arr.reduce((acc,cur) => acc+cur); 이런식의 코드인데,
//뒤에 0을 붙인 이유는 초기값이다. 더해줄값이 없다면, 즉 빈배열이라면 0을 리턴한다.
//if문으로 따로 써도 인정된다.
  1. number 타입을 요소로 갖는 배열을 입력받아 배열의 모든 요소의 곱을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    반드시 arr.reduce를 이용해서 풀어야 합니다.
    빈 배열을 입력받은 경우, 1을 리턴해야 합니다.
function computeProductOfAllElements(arr) {
  return arr.reduce((acc, val) => {return acc * val;}, 1);
}
//모든요소 곱셈은 원래 arr.reduce((acc, val) => acc * val); 이런 코드를 짜도 되지만
//만약 빈배열이라면, 처음부터 곱해줄값이 없으므로 empty값이 나오므로 초기값 1을 세팅한다
  1. number 타입을 요소로 갖는 배열을 입력받아 배열의 모든 요소의 평균을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    반드시 arr.reduce를 이용해서 풀어야 합니다.
    빈 배열을 입력받은 경우, 0을 리턴해야 합니다.
function computeAverageOfNumbers(arr) {
  if(arr.length === 0) return 0;
  return arr.reduce((acc, cur) => acc + cur)/arr.length;

}
//arr.reduce((acc, cur) => {return acc + cur;}, 0)/arr.length;
//위의 코드가 안되는 이유는 0/0 = NaN이 되기 때문이다.
//그래서 따로 if문으로 빈배열 인 경우 0을 리턴하라는 코드를 써야 한다.
  1. 객체를 요소로 갖는 배열과 문자열을 입력받아 각 요소의 'animal' 속성값이 문자열과 일치할 경우, 해당 요소의 'score' 속성값을 모두 더한 값을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    빈 배열을 입력받은 경우, 0을 리턴해야 합니다.
function calculateScore(records, value) {
  return records.filter(v => v.animal === value).map(v => v.score).reduce((acc,cur) => {return acc+cur},0);
}
//객체를 요소로 갖는 records배열
//records의 요소인 객체.animal === 문자열value 라면 filter로 적용
//-> map으로 객체.score 가져오기
//-> reduce로 score 다 더하기, 만약 지금 배열이 빈배열이라면 0을 리턴
  1. 문자열을 요소로 갖는 배열을 입력받아 배열에서 가장 긴 문자열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    가장 긴 문자열이 중복이 될 경우, 앞 쪽에 있는 요소를 리턴해야 합니다.
    빈 배열을 입력받은 경우, 빈 문자열을 리턴해야 합니다.
function getLongestElement(arr) {
  if(arr.length === 0) return "";
  return arr.reduce((a,b) => a.length>=b.length ? a:b);
}
//문자열을 요소로 갖는 배열 arr
//요소 중 가장 긴 문자열을 리턴
  1. 문자열을 요소로 갖는 배열을 입력받아 배열에서 가장 긴 문자열의 길이를 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    빈 배열을 입력받은 경우, 0을 리턴해야 합니다.
function getLengthOfLongestElement(arr) {
  if(arr.length === 0) return 0;
  return arr.reduce((a,b) => a.length>=b.length ? a:b).length;

}
//배열 arr에서 가장 긴 문자열의 길이를 리턴
//reduce의 값은 acc에 length를 붙이면 cur에서는 cur.length.length가 됨
  1. 2차원 배열(배열을 요소로 갖는 배열)을 입력받아 배열들의 요소를 모두 담고 있는 단일 배열을 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    arr.flat 사용은 금지됩니다.
function joinArrayOfArrays(arr) {
  return arr.reduce((acc,cur) => acc.concat(cur));
}
//배열을 요소로 갖는 배열 arr 의 단일배열 리턴
  1. 배열을 입력받아 배열에서 가장 짧은 길이를 가진 문자열 요소를 리턴해야 합니다.
    반복문(for, while) 사용은 금지됩니다.
    같은 길이의 요소가 있다면 배열의 앞쪽에 있는 요소를 리턴해야 합니다.
    배열에는 문자열 외에 다른 요소들이 있을 수 있습니다.
    빈 배열을 입력받은 경우, 빈 문자열을 리턴해야 합니다.
    주어진 배열에 문자열이 없는 경우, 빈 문자열을 리턴해야 합니다.
function findShortestWord(arr) {
  if(arr.length === 0) return "";
  let newArr = arr.filter(v=> typeof(v)==="string");
  if(newArr.length === 0){
    return "";
  }
  return newArr.reduce((a,b) => a.length<=b.length ? a:b);
}

//문자열을 요소로 갖는 배열 arr
//요소 중 가장 짧은 문자열을 리턴
  1. 학생의 정보가 담긴 객체를 요소로 갖는 배열을 입력받아 아래 조건에 맞게 변형된 배열을 리턴해야 합니다.(어려움 ⭐⭐⭐⭐⭐⭐⭐)
    남학생들의 정보는 리턴하는 배열에서 제외합니다.
    'grades' 속성값은 평균값(number 타입)으로 바꿉니다.
    반복문(for, while) 사용은 금지됩니다.
    배열을 리턴해야 합니다.
    배열로 되어 있는 학생들의 성적을 number 타입의 평균값으로 변형해야 합니다.
    'female'는 여학생, 'male'는 남학생입니다.
function studentReports(students) {
  return students.filter(v => v.gender === "female").map(el => {
    el.grades = el.grades.reduce((acc,cur) => {return acc+cur;},0)/ el.grades.length;
    return el;
  });
}
//students배열중 gender가 여자인 배열만 filter
//map grades배열요소의 평균을 구해서 다시 grades값으로 바꾸기
//map을 쓸 때 el요소안에 있는 것만 바꿔서 다시 el로 내보내고 싶다하면,
//map(el => {el.grades = el.grades.reduce().....return el})하면 된다.
  1. 2차원 배열(배열을 요소로 갖는 배열)을 입력받아 모든 수(number)의 합을 리턴해야 합니다.
    합을 구할 때 number 타입만 고려해야 합니다. (어려움 ⭐⭐⭐⭐⭐⭐)
function sumOfArraysInArray(arr) {
  return arr.reduce((acc, cur) => acc.concat(cur)).filter(v => typeof(v) === 'number').reduce((acc, cur) => {return acc+cur},0);
}
//arr배열중 배열요소들을 모두 합쳐서 한 배열로 만들기 위해 reduce, concat
//한 배열의 요소들 중 숫자인 요소만 filter
//reduce로 숫자들의 합을 구하기
//++배열에 숫자가 없는 배열이면 0을 리턴한다. 할때,
//reduce((acc, cur) => {return acc+cur},0); 이런식으로 쓴다. 0을 안쓰면 empty가 뜬다.
profile
신입 프론트엔드 웹 개발자입니다.

1개의 댓글

comment-user-thumbnail
2023년 1월 12일

오늘은 유난히 양이 더 많아 보이네요ㅎㅎ
내용도 지나칠 것 없이 전부 알찬 내용들 밖에 없네요!

답글 달기