문제

다음을 사용하여 항목 배열을 필터링하고 싶습니다. 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"]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top