【问题标题】:How to get filtered in and out elements of array at one go in Javascript如何在Javascript中一次性过滤进出数组元素
【发布时间】:2020-03-21 20:39:47
【问题描述】:

我想知道是否有一种精确的方法可以在 Javascript 中过滤数组中未过滤的元素,我的意思是,一次完成。

目前,我使用如下逻辑:

const myArray = ['a', 'b', 'c', 'd', 'e']
const filterArray = ['a', 'b']

// I want to combine those two expressions somehow
const filteredInResult = myArray.filter(e => filterArray.includes(e))
const filteredOutResult = myArray.filter(e => !filterArray.includes(e))

console.log(filteredInResult)
console.log(filteredOutResult)

我觉得可能已经有类似destructuring 的方式来实现它,但无论如何,我更喜欢问你们是否有一种方法可以一次性过滤出和过滤出结果。

编辑: 如果这个问题与问题here 相似,SO 会一直提醒我,但我使用字符串比较和includes 进行上述酿造,但过滤表达式可能比这更复杂.所以,我必须强调问题的重点不是两个字符串数组的差异。我要留下另一个例子,希望问题不会被合并:D

// A more complex use case
const myArray = [
  {id: 1, value: 'a'},
  {id: 2, value: 'b'},
  {id: 3, value: 'c'},
  {id: 4, value: 'd'},
  {id: 5, value: 'e'},
]
const filterArray = ['a', 'b']

// I want to combine those two expressions somehow
const filteredInResult = myArray.filter(e => filterArray.includes(e.value))
const filteredOutResult = myArray.filter(e => !filterArray.includes(e.value))

console.log(filteredInResult)
console.log(filteredOutResult)

【问题讨论】:

  • 意识到“一次性”是上下文相关的。在答案和问题示例中,“包含”的使用是对表达循环的每次迭代进行查找(内部循环)。在任何情况下都不会有“一次性”解决方案。
  • @JuhilSomaiya 不,我编辑并添加了另一个用例,以表明结构相似的数组并不总是差异

标签: javascript arrays filter


【解决方案1】:

如果您担心对 myArray 进行两次迭代,您可能首先考虑降低计算复杂度。因为循环的每次迭代都调用Array.prototype.includes,而Array.prototype.includes 的复杂度为O(n),所以您的代码的总体复杂度为O(n ^ 2)。 (外循环:O(n) * 内循环:O(n))。因此,请考虑先解决该问题:使用 Set 和 Set.hasO(1) 操作,而不是数组和 .includes。这是假设您的实际 filterArray 足够大以至于需要担心计算复杂性 - 集合 确实 有一些开销成本。

至于问题的另一(主要)部分,一种选择是在外面创建两个结果数组,然后在迭代时推送到适当的数组:

const myArray = ['a', 'b', 'c', 'd', 'e']
const filterArray = new Set(['a', 'b'])

const filteredInResult = [];
const filteredOutResult = [];
for (const e of myArray) {
  (filterArray.has(e) ? filteredInResult : filteredOutResult).push(e);
}
console.log(filteredInResult)
console.log(filteredOutResult)

也可以用reduce,虽然我觉得不太好看:

const myArray = ['a', 'b', 'c', 'd', 'e']
const filterArray = new Set(['a', 'b'])

const { filteredInResult, filteredOutResult } = myArray.reduce((a, e) => {
  a[filterArray.has(e) ? 'filteredInResult' : 'filteredOutResult'].push(e);
  return a;
}, { filteredInResult: [], filteredOutResult: [] });

console.log(filteredInResult)
console.log(filteredOutResult)

【讨论】:

    【解决方案2】:

    您可以使用.reduce() 而不是.filter(),您可以使用includes() 的(数字)布尔值作为累加器的索引,如下所示:

    const myArray = ['a', 'b', 'c', 'd', 'e'];
    const filterArray = ['a', 'b'];
    
    const [fOut, fIn] = myArray.reduce((a, n) => {
      a[+filterArray.includes(n)].push(n); 
      return a;
    }, [[], []]);
    
    console.log(fIn);
    console.log(fOut);

    【讨论】:

      【解决方案3】:

      一个带有ramda的partition的解决方案。

      const
          array = ['a', 'b', 'c', 'd', 'e'],
          filter = ['a', 'b'],
          [filteredInResult, filteredOutResult] = R.partition(v => filter.includes(v), array);
      
      console.log(...filteredInResult); // a b
      console.log(...filteredOutResult) // c d e
      <script src="http://cdn.jsdelivr.net/ramda/latest/ramda.min.js"></script>

      【讨论】:

        【解决方案4】:

        我无法破坏,但这似乎比其他地方提供的 reduce 更容易阅读

        const myArray = ['a', 'b', 'c', 'd', 'e']
        const filterArray = ['a', 'b']
        let filteredOutResult = [];
        
        const filteredInResult = myArray.filter(item => { 
           if (filterArray.includes(item)) return item; 
           filteredOutResult.push(item); 
        });
        
        console.log(filteredInResult,filteredOutResult)
         

        【讨论】:

          【解决方案5】:

          一个本地答案是使用Array#reduce

          const { in, out } = myArr.reduce((acc, v) => {
            (filterArray.includes(v) ? acc.in : acc.out).push(v);
            return acc;
          }, { in: [], out: [] });
          

          然后解构返回的对象

          【讨论】:

            猜你喜欢
            • 2020-04-29
            • 2022-12-06
            • 1970-01-01
            • 2019-01-03
            • 2020-12-20
            • 2012-09-17
            • 2020-07-15
            • 2022-11-25
            • 2020-11-23
            相关资源
            最近更新 更多