Underbar
take
문제
// _.take는 배열의 처음 n개의 element를 담은 새로운 배열을 리턴합니다.
// n이 undefined이거나 음수인 경우, 빈 배열을 리턴합니다.
// n이 배열의 길이를 벗어날 경우, 전체 배열을 shallow copy한 새로운 배열을 리턴합니다.
_.take = function (arr, n) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.take = function (arr, n) {
if (!n) {
return []; // n이 아닐경우 빈배열 리턴
}
return _.slice(arr, 0, n); // 맞다면 배열에 0번째 인덱스부터 n번까지
};
drop
문제
// _.drop는 _.take와는 반대로, 처음 n개의 element를 제외한 새로운 배열을 리턴합니다.
// n이 undefined이거나 음수인 경우, 전체 배열을 shallow copy한 새로운 배열을 리턴합니다.
// n이 배열의 길이를 벗어날 경우, 빈 배열을 리턴합니다.
_.drop = function (arr, n) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.drop = function (arr, n) {
return _.slice(arr, n); // 배열에 n번 리턴
};
last
문제
// _.last는 배열의 마지막 n개의 element를 담은 새로운 배열을 리턴합니다.
// n이 undefined이거나 음수인 경우, 배열의 마지막 요소만을 담은 배열을 리턴합니다.
// n이 배열의 길이를 벗어날 경우, 전체 배열을 shallow copy한 새로운 배열을 리턴합니다.
// _.take와 _.drop 중 일부 또는 전부를 활용할 수 있습니다.
_.last = function (arr, n) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.last = function (arr, n) {
if (n === undefined) { // n이 undefined이거나 음수인 경우
return _.slice(arr, -1); // 배열의 마지막 요소만을 담은 배열을 리턴
} else if (n > arr.length) { // n이 배열의 길이를 벗어날 경우
return _.slice(arr); // 전체 배열을 shallow copy한 새로운 배열을 리턴
} else if (n === 0) { // n이 0일 경우
return []; // 빈배열 리턴
} else { // 모두 통과하면
return _.slice(arr, n - 1); // 배열의 마지막 n개의 element를 담은 새로운 배열을 리턴
}
};
each
문제
// _.each는 명시적으로 어떤 값을 리턴하지 않습니다.
_.each = function (collection, iteratee) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.each = function (collection, iteratee) {
// TODO: 여기에 코드를 작성합니다.
//1. collection(배열 혹은 객체)과 함수 iteratee(반복되는 작업)를 인자로 전달받아 (iteratee는 함수의 인자로 전달되는 함수이므로 callback 함수)
if (Array.isArray(collection)) {
// collection이 배열이라면?
//Array.isArray() 메서드는 collection가 Array인지 판별
//2. collection의 데이터(element 또는 property)를 순회하면서
for (let i = 0; i < collection.length; i++) {
//3. iteratee에 각 데이터를 인자로 전달하여 실행합니다.
iteratee(collection[i], i, collection); //iteratee(ele, idx, arr)
}
} else {
//collection이 배열이 아닌 객체라면?
for (let num in collection) {
// collection[num]
//상속된 열거 가능한 속성들을 포함하여 객체에서 문자열로 키가 지정된 모든 열거 가능한 속성에 대해 반복
//3. iteratee에 각 데이터를 인자로 전달하여 실행합니다.
iteratee(collection[num], num, collection); // collection[i] //iteratee(val, key, obj)
}
}
};
indexOf
문제
// _.indexOf는 target으로 전달되는 값이 arr의 요소인 경우, 배열에서의 위치(index)를 리턴합니다.
// 그렇지 않은 경우, -1을 리턴합니다.
// target이 중복해서 존재하는 경우, 가장 낮은 index를 리턴합니다.
_.indexOf = function (arr, target) {
// 배열의 모든 요소에 접근하려면, 순회 알고리즘(iteration algorithm)을 구현해야 합니다.
// 반복문을 사용하는 것이 가장 일반적이지만, 지금부터는 이미 구현한 _.each 함수를 활용하여야 합니다.
// 아래 _.indexOf의 구현을 참고하시기 바랍니다.
let result = -1;
_.each(arr, function (item, index) {
if (item === target && result === -1) {
result = index;
}
});
return result;
};
filter
문제
// _.filter는 test 함수를 통과하는 모든 요소를 담은 새로운 배열을 리턴합니다.
// test(element)의 결과(return 값)가 truthy일 경우, 통과입니다.
// test 함수는 각 요소에 반복 적용됩니다.
// _.each는 collection의 각 데이터에 반복적인 작업을 수행합니다.
_.filter = function (arr, test) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.filter = function (arr, test) {
// 통과하는 모든 요소를 담은 새로운 배열을 리턴 (truthy일 경우, 통과)
// TODO: 여기에 코드를 작성합니다.
let result = []; // 통과 된 요소를 새로운 배열로 담을 result.
//_.each (collection(배열 혹은 객체), 함수 iteratee(반복되는 작업))
_.each(arr, function (ele) {
if (test(ele)) {
// 참(truthy)이라면
result.push(ele); // result에 ele 추가
}
});
return result;
};
reject
문제
// _.reject는 _.filter와 정반대로 test 함수를 통과하지 않는 모든 요소를 담은 새로운 배열을 리턴합니다.
_.reject = function (arr, test) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.reject = function (arr, test) {
// TODO: 여기에 코드를 작성합니다.
let result = []; // 통과 된 요소를 새로운 배열로 담을 result.
//_.each (collection(배열 혹은 객체), 함수 iteratee(반복되는 작업))
_.each(arr, function (ele) {
if (!test(ele)) {
// _.filter에 반대라서 ! 부정 추가
result.push(ele); // result에 ele 추가
}
});
return result;
};
uniq
문제
// _.uniq는 주어진 배열의 요소가 중복되지 않도록 새로운 배열을 리턴합니다.
// 중복 여부의 판단은 엄격한 동치 연산(strict equality, ===)을 사용해야 합니다.
// 입력으로 전달되는 배열의 요소는 모두 primitive value라고 가정합니다.
_.uniq = function (arr) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.uniq = function (arr) {
// TODO: 여기에 코드를 작성합니다.
let result = []; // 새로운 배열로 담을 result.
_.each(arr, function (ele) {
if (_.indexOf(result, ele) === -1) {
// 중복이 되는지
result.push(ele); // result push
}
});
return result;
};
map
문제
// _.map은 iteratee(반복되는 작업)를 배열의 각 요소에 적용(apply)한 결과를 담은 새로운 배열을 리턴합니다.
// 함수의 이름에서 드러나듯이 _.map은 배열의 각 요소를 다른 것(iteratee의 결과)으로 매핑(mapping)합니다.
_.map = function (arr, iteratee) {
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.map = function (arr, iteratee) {
// TODO: 여기에 코드를 작성합니다.
// _.map 함수는 매우 자주 사용됩니다.
// _.each 함수와 비슷하게 동작하지만, 각 요소에 iteratee를 적용한 결과를 리턴합니다.
let result = [];
_.each(arr, function (ele) {
result.push(iteratee(ele));
});
return result;
};
pluck
문제
// _.pluck은
// 1. 객체 또는 배열을 요소로 갖는 배열과 각 요소에서 찾고자 하는 key 또는 index를 입력받아
// 2. 각 요소의 해당 값 또는 요소만을 추출하여 새로운 배열에 저장하고,
// 3. 최종적으로 새로운 배열을 리턴합니다.
// 예를 들어, 각 개인의 정보를 담은 객체를 요소로 갖는 배열을 통해서, 모든 개인의 나이만으로 구성된 별도의 배열을 만들 수 있습니다.
// 최종적으로 리턴되는 새로운 배열의 길이는 입력으로 전달되는 배열의 길이와 같아야 합니다.
// 따라서 찾고자 하는 key 또는 index를 가지고 있지 않은 요소의 경우, 추출 결과는 undefined 입니다.
_.pluck = function (arr, keyOrIdx) {
// _.pluck을 _.each를 사용해 구현하면 아래와 같습니다.
// let result = [];
// _.each(arr, function (item) {
// result.push(item[keyOrIdx]);
// });
// return result;
// _.pluck은 _.map을 사용해 구현하시기 바랍니다.
//
// TODO: 여기에 코드를 작성합니다.
}
풀이
_.pluck = function (arr, keyOrIdx) {
return _.map(arr, function (ele) {
return ele[keyOrIdx];
});
};
reduce
풀이
_.reduce = function (arr, iteratee, initVal) {
let result = initVal; //
_.each(arr, function (item, idx, items) {
// _.each 메서드에 반복할 iteratee 사용
//
if (initVal === undefined && idx === 0) {
//입력받은 초기값이 없을경우,
result = item; //배열의 첫번째 요소를 할당한다.
} else {
//그 외에는
result = iteratee(result, item, idx, items);
}
});
return result;
};