代码之家  ›  专栏  ›  技术社区  ›  Rewind

如何在使用javascript的过滤器时获取排除的元素

  •  1
  • Rewind  · 技术社区  · 3 年前

    Javascript的 filter 返回包含所有通过测试的元素的数组。

    如何在不重新运行测试的情况下轻松获取所有未通过测试的元素,但反过来呢?即使你必须再次运行测试,最好的方法是如何做到这一点。

    let arr; // this is the array on which the filter will be run [SET ELSEWHERE]
    let fn; // The filter function [SET ELSEWHERE]
    let goodElements; // This will be the new array of the good elements passing the test
    let badElements; // This will be the new array of the elements failing the test
    
    goodElements = arr.filter(fn);
    
    // SO HOW IS badElements set????
    

    怎么样 badElements 设置

    5 回复  |  直到 3 年前
        1
  •  3
  •   Spectric amamoto    3 年前

    如果不想进行两次迭代,可以使用 for 循环和三元运算符:

    let arr = [1, 2, 3];
    let fn = (e) => e % 2 == 0;
    let goodElements = [];
    let badElements = [];
    
    for(const e of arr) (fn(e) ? goodElements : badElements).push(e);
    console.log(goodElements);
    console.log(badElements);

    否则,只需使用反转条件 ! 操作人员

    let arr = [1, 2, 3];
    let fn = (e) => e % 2 == 0;
    let goodElements;
    let badElements;
    
    goodElements = arr.filter(fn);
    badElements = arr.filter(e => !fn(e));
    console.log(goodElements);
    console.log(badElements);
        2
  •  3
  •   Barmar    3 年前

    不使用 filter() 。如果你想把数据分成两个数组,那就自己做吧。

    function partition(array, fn) {
      let goodArray = [],
        badArray = [];
      array.forEach(el => {
        if (fn(el)) {
          goodArray.push(el);
        } else {
          badArray.push(el);
        }
      });
      return [goodArray, badArray];
    }
    
    let [goodElemements, badElements] = partition(arr, fn);
    

    您也可以使用 reduce()

    function partition(array, fn) {
      return array.reduce(acc, el => {
        if (fn(el)) {
          acc[0].push(el);
        } else {
          acc[1].push(el);
        }
      }, [[],[]]);
    }
    
    let [goodElemements, badElements] = partition(arr, fn);
    
        3
  •  2
  •   tarkh    3 年前

    如果你想严格遵守 Array.filter 只有一个循环,然后考虑这样的事情:

    UPD:基于 @AlvaroFlañoLarrondo 评论,为当前方法添加了外部条件函数。

    // Array of elements
    const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
    
    // External filter method
    const fn = e => e.length > 6;
    
    // Define empty bad array
    const bad = [];
    
    // Define good array as result from filter function
    const good = words.filter(word => {
      // In filter condition return good values
      if(fn(word)) return word;
      // And skip else values by just pushing them
      // to bad array, without returning
      else bad.push(word);
    });
    
    // Results
    console.log(good);
    console.log(bad);
        4
  •  1
  •   Guerric P    3 年前

    你可以使用 reduce 以便根据谓词将数组拆分为两个数组,如本例所示:

    const arr = [1, 0, true, false, "", "foo"];
    const fn = element => !element;
    
    const [goodElements, badElements] = arr.reduce(
      ([truthies, falsies], cur) =>
        fn(cur) ? [truthies, [...falsies, cur]] : [[...truthies, cur], falsies],
      [[], []]
    );
    
    console.log(goodElements, badElements);
        5
  •  1
  •   Snowmonkey    3 年前

    我看到了两条可能的路线:

    // in this case, if it's not in `goodElements`, it's a bad 'un
    badElements = arr.filter( el => !goodElements.includes(el) );
    

    或者这样:

    // we don't **know** if fn needs the optional parameters, so we will
    //  simply pass them. If it doesn't need 'em, they'll be ignored.
    badElements = arr.filter( (el, idx, arr) => !fn(el, idx, arr) );
    
        6
  •  0
  •   ManuelMB    3 年前
    const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    const fn = (x) => x % 2 === 0
    
    const removeItems = (array, itemsToRemove) => {
        return array.filter(v => {
          return !itemsToRemove.includes(v);
        });
    }
      
    const goodElements = arr.filter(fn)
    console.log(goodElements) // [ 0, 2, 4, 6, 8 ]
    
    const badElements = removeItems(arr, goodElements)
    console.log(badElements) // [ 1, 3, 5, 7, 9 ]