JavaScript에서 Array.map을 사용하여 요소 제거
문제
다음을 사용하여 항목 배열을 필터링하고 싶습니다. map()
기능.다음은 코드 조각입니다.
var filteredItems = items.map(function(item)
{
if( ...some condition... )
{
return item;
}
});
문제는 필터링된 항목이 여전히 배열의 공간을 사용하므로 해당 항목을 완전히 지우고 싶다는 것입니다.
어떤 아이디어?
편집하다:고마워요, 잊어버렸어요 filter()
, 제가 원했던 것은 사실 filter()
그 다음에 map()
.
편집2:지적해주셔서 감사합니다 map()
그리고 filter()
내 특정 코드는 브라우저에서 실행되도록 의도되지 않았지만 모든 브라우저에서 구현되지는 않습니다.
해결책
당신은 filter
필터링 외에 배열의 항목을 변경하려는 경우가 아니면 맵 대신 메서드를 사용하세요.
예.
var filteredItems = items.filter(function(item)
{
return ...some condition...;
});
[편집하다:물론 언제나 그럴 수도 있지 sourceArray.filter(...).map(...)
필터링 및 변경 모두]
다른 팁
얼마전에 답변을 썼는데 생각이 바뀌었어요.내 것을 확인해 보는 것이 좋습니다. 블로그 게시물 이 주제를 확장하고 훨씬 더 잘 설명합니다.또한 대안 끝에 JSperf 비교도 제공됩니다.
요약하자면 다음과 같습니다.원하는 작업(하나의 함수 호출 내에서 필터링 및 매핑)을 수행하려면 다음을 사용해야 합니다. Array.reduce()
.그러나, 그 더 읽기 쉬움 그리고 보통 더 빠르다2 접근 방식은 필터와 맵을 함께 연결하여 사용하는 것입니다.
[1,2,3].filter(num => num > 2).map(num => num * 2)
다음은 방법에 대한 설명입니다. Array.reduce()
작동하는 방법과 한 번의 반복으로 필터와 매핑을 수행하는 데 어떻게 사용할 수 있는지 알아보세요.이것이 너무 압축되어 있다면 위에 링크된 블로그 게시물을 참조하는 것이 좋습니다. 이 게시물은 명확한 예와 진행 상황이 포함된 훨씬 더 친숙한 소개입니다.
(보통 익명) 함수인 인수를 축소합니다.
그 익명 함수 두 개의 매개변수를 사용합니다. 하나는(map/filter/forEach에 전달된 익명 함수와 같은) 작업할 반복 대상입니다.그러나 Reduce에 전달된 익명 함수에 대한 또 다른 주장은 해당 함수가 허용하지 않는다는 것입니다. 함수 호출 사이에 전달될 값(종종 메모.
Array.filter()는 하나의 인수(함수)만 사용하는 반면 Array.reduce()는 중요한(선택 사항이지만) 두 번째 인수도 사용합니다.첫 번째 인수로 익명 함수에 전달될 'memo'의 초기 값은 이후에 함수 호출 사이에 변경되어 전달될 수 있습니다.(제공되지 않으면 첫 번째 익명 함수 호출의 'memo'는 기본적으로 첫 번째 반복 대상이 되고 '반복 대상' 인수는 실제로 배열의 두 번째 값이 됩니다)
우리의 경우 빈 배열을 전달하여 시작한 다음 반복 대상을 배열에 삽입할지 여부를 함수에 따라 선택합니다. 이것이 필터링 프로세스입니다.
마지막으로, 각 익명 함수 호출에서 '진행 중인 배열'을 반환하고, 축소는 해당 반환 값을 가져와 다음 함수 호출에 인수(메모라고 함)로 전달합니다.
이를 통해 필터와 맵을 한 번의 반복으로 수행할 수 있으므로 필요한 반복 횟수가 절반으로 줄어듭니다.:)
더 자세한 설명은 다음을 참조하세요. MDN 아니면 위 링크.:)
Reduce 통화의 기본 예:
let array = [1,2,3];
const initialMemo = [];
array = array.reduce((memo, iteratee) => {
// if condition is our filter
if (iteratee > 1) {
// what happens inside the filter is the map
memo.push(iteratee * 2);
}
// this return value will be passed in as the 'memo' argument
// to the next call of this function, and this function will have
// every element passed into it at some point.
return memo;
}, initialMemo)
console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]
더 간결한 버전:
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
첫 번째 반복 대상은 1보다 크지 않으므로 필터링되었습니다.또한 존재를 명확하게 하고 관심을 끌기 위해 이름을 붙인 초기 메모도 참고하세요.다시 한번, 첫 번째 익명 함수 호출에 'memo'로 전달되고, 익명 함수의 반환 값이 다음 함수에 'memo' 인수로 전달됩니다.
메모의 전형적인 사용 사례의 또 다른 예는 배열에서 가장 작거나 가장 큰 숫자를 반환하는 것입니다.예:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.
자신만의 축소 함수를 작성하는 방법에 대한 예(이는 종종 다음과 같은 함수를 이해하는 데 도움이 됩니다):
test_arr = [];
// we accept an anonymous function, and an optional 'initial memo' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
// if we did not pass in a second argument, then our first memo value
// will be whatever is in index zero. (Otherwise, it will
// be that second argument.)
const initialMemoIsIndexZero = arguments.length < 2;
// here we use that logic to set the memo value accordingly.
let memo = initialMemoIsIndexZero ? this[0] : initialMemo;
// here we use that same boolean to decide whether the first
// value we pass in as iteratee is either the first or second
// element
const initialIteratee = initialMemoIsIndexZero ? 1 : 0;
for (var i = initialIteratee; i < this.length; i++) {
// memo is either the argument passed in above, or the
// first item in the list. initialIteratee is either the
// first item in the list, or the second item in the list.
memo = reduceFunc(memo, this[i]);
}
// after we've compressed the array into a single value,
// we return it.
return memo;
}
예를 들어 실제 구현을 통해 인덱스와 같은 항목에 액세스할 수 있지만 이것이 요점에 대한 복잡하지 않은 느낌을 얻는 데 도움이 되기를 바랍니다.
지도는 그렇지 않습니다.당신은 정말로 원해요 배열.필터.또는 원본 목록에서 요소를 정말로 제거하려면 for 루프를 사용하여 명령적으로 제거해야 합니다.
그러나 당신은 Array.filter
모든 브라우저에서 지원되지는 않으므로 프로토타입을 제작해야 합니다.
//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
if (!Array.prototype.filter)
{
Array.prototype.filter = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var res = new Array();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
{
var val = this[i]; // in case fun mutates this
if (fun.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
}
그렇게 하면 필요한 모든 방법의 프로토타입을 만들 수 있습니다.
이 페이지에 공유된 폴리필이 형편없기 때문에 여기에 답변을 배치했습니다.
function reduce(f, y, xs, context) {
var acc = y;
for (var i = 0, len = xs.length; i < len; i++)
acc = f.call(context, acc, xs[i], i, xs);
return acc;
}
function reduce1(f, xs, context) {
if (xs.length === 0)
throw Error('cannot reduce empty array without initial value');
else
return reduce(f, xs[0], xs.slice(1), context);
}
function map(f, xs, context) {
return reduce(function(acc, x, i) {
return acc.concat([
f.call(context, x, i, xs)
]);
}, [], xs);
}
function filter(f, xs, context) {
return reduce(function(acc, x, i) {
if (f.call(context, x, i, xs))
return acc.concat([x]);
else
return acc;
}, [], xs);
}
프로토타입 확장
if (Array.prototype.reduce === undefined) {
Array.prototype.reduce = function(f, initialValue, context) {
if (initialValue === undefined)
return reduce1(f, this, context);
else
return reduce(f, initialValue, this, context);
};
}
if (Array.prototype.map === undefined) {
Array.prototype.map = function(f, context) {
return map(f, this, context);
};
}
if (Array.prototype.filter === undefined) {
Array.prototype.filter = function(f, context) {
return filter(f, this, context);
};
}
var arr = [1,2,'xxx','yyy']
arr = arr.filter(function(e){ return e != 'xxx' });
arr // [1, 2, "yyy"]