使用Array.prototype.reduce进行数组交集(集合论)

4

我有两个数组[a,b,c,d][b,d,f,h]

我想要返回一个包含共同元素[b,d]的数组。

我可以通过使用filterindexOf的组合来实现:

[a,b,c,d].filter(el => [b,d,f,h].indexOf(el) !== -1)

但我想知道如何使用reduce来实现同样的效果。

我承认,尽管看了很多例子,reduce仍然是我觉得最难理解的JS方法之一,所以我非常希望能得到一些建议。


尝试使用 reduce 实现 filter - Bergi
3个回答

6

ES6,一个提案,包括Array#includes

includes()方法确定数组是否包含某个元素,适当时返回truefalse

在每次循环aa时,reduce将元素添加到结果数组中,如果值在测试数组bb中找到。如果未找到,则返回先前的结果。

var aa = ['a','b','c','d'],
    bb = ['b','d','f','h'],
    cc = aa.reduce((r, a) => bb.includes(a) && r.concat(a) || r, []);

console.log(cc);

只需使用一个包含所有数组的单个数组,就可以更智能地处理。

var aa = ['a','b','c','d'],
    bb = ['b','d','f','h'],
    result = [aa, bb].reduce((a, b) => a.filter(c => b.includes(c)));

console.log(result);


我非常喜欢,谢谢!你知道使用 reduce 来实现相同的结果的方法吗? - U r s u s
你的意思是不包括includes或者indexof吗? - Nina Scholz
1
好的回答,Nina!我不知道你代码的确切行为,所以我做了一个 fiddle 来更好地理解你的代码。可能会对某些人有帮助 :-) https://jsfiddle.net/joherro3/c69vgzL4/2/ - Jose Hermosilla Rodrigo
reduce 更多地用于返回一个单一的值(可以是对象或数组)与某些操作。最常用的例子是对数组进行加法运算并返回总和。这里有一个数组,结果并不好,因为这种方式的使用不好,因为值始终相同(即数组本身),而不是原始值。 - Nina Scholz
1
@JoseHermosillaRodrigo,对的,它是if的简写形式...或者更好地说是三元运算符。 - Nina Scholz
显示剩余3条评论

2

Reduce旨在从一组项目中返回单个值。因此,这里使用过滤器更有意义。

使用reduce的好方法是返回共同元素的总数。 在此处查看:https://jsfiddle.net/c69vgzL4/

var a = ['a','b','c','d']
var b = ['b','d','f','h']

var number_of_common = b.reduce(function(prev, next) {
    return prev + (a.indexOf(next) + 1 ? 1 : 0)
}, 0)

$('body').html(number_of_common)

1

不仅限于两个数组,对于n个数组的交集...我们可以创造一个Array.prototype.intersect()方法

Array.prototype.intersect = function(...a) {
  return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
}

var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]],
     arr = [0,1,2,3,4,5,6,7,8,9];

console.log(JSON.stringify(arr.intersect(...arrs)));

// or just do

console.log(JSON.stringify(["a","b","c","d"].intersect(["b","d","f","h"])));


你需要JSON.stringify吗? - U r s u s
@U r s u s 实际上不是,但它会水平显示数组和对象。 - Redu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接