使用array.filter函数,我可以有效地抽出所有满足或不满足条件的元素:

let large = [12, 5, 8, 130, 44].filter((x) => x > 10);
let small = [12, 5, 8, 130, 44].filter((x) => !(x > 10));


但是,在上面的示例中,我是在数组上迭代两次,并每次执行相同的测试。是否有一种简单的方法可以通过数组一次生成“大”和“小”?特别是,如果用于评估是否应保留元素的回调很昂贵,则我希望避免两次调用它。

#1 楼

使用TypeScript / ECMAScript 6语法可以通过这种方式实现。我不确定它是否比原始版本更优雅,但是


可以完成;
只需要运行一次;
可以进一步与map ()或其他功能链接在一起。


const [small, large] =                             // Use "deconstruction" style assignment
  [12, 5, 8, 130, 44]
    .reduce((result, element) => {
      result[element <= 10 ? 0 : 1].push(element); // Determine and push to small/large arr
      return result;
    },
    [[], []]);                                     // Default small/large arrays are empty



更多选项可以在各种StackOverflow问题中找到。

#2 楼

天真的方式有什么问题吗?

let large = [];
let small = [];

array.forEach((x) => (x > 10 ? large : small).push(x));

// or
for(const x of array){
    (x > 10 ? large : small).push(x);
}


评论


\ $ \ begingroup \ $
为什么用map代替forEach?
\ $ \ endgroup \ $
– xehpuk
18年2月15日在20:22

\ $ \ begingroup \ $
@xehpuk你说得对,因为这里的每个都会更好。更新了答案。
\ $ \ endgroup \ $
– Qtax
18年2月19日在10:27

#3 楼

现有答案似乎无法解决回调问题。包括它的一种方法可能是:

const partition = (ary, callback) =>
  ary.reduce((acc, e) => {
    acc[callback(e) ? 0 : 1].push(e)
    return acc
  }, [[], []])


并像这样使用它:

let [large, small] = partition([12, 5, 8, 130, 44], (x => x > 10))


评论


\ $ \ begingroup \ $
虽然我认为将分区函数中的谓词称为“回调”有点含糊,但实际上它是您发布的一个不错的解决方案。 👍
\ $ \ endgroup \ $
–rishat
18-2-19在15:13

\ $ \ begingroup \ $
@RishatMuhametshin命名法来自OP
\ $ \ endgroup \ $
– morbusg
18年2月19日在15:16

\ $ \ begingroup \ $
重新阅读它后,我对使用“回调”一词感到有些惊讶。实际上,我认为促使我提出此问题的代码涉及一系列承诺,因此“回调”是描述谓词的一种特别不合适的方式。
\ $ \ endgroup \ $
–马克斯·罗塞特(Max Rosett)
18年2月19日在19:12

\ $ \ begingroup \ $
通常,您会使用谓词作为名称。
\ $ \ endgroup \ $
–克里斯蒂安·伊维切维奇
19年8月23日在14:33