在JavaScript中进行左外连接

3
我在javascript(D3)中有一个对象数组,需要删除另一个对象属性中存在特定属性的每个对象,即左外连接。full outer join
(来源: tazindeed.co.uk) 我已经用两个循环自己完成了这个过程,但速度相当慢。而且我不知道如何加快速度。
    for (var i = 0; i < data1.length; i++) {
        for (var j = 0; j < data2.length; j++) {
            if (data2[j].attr3 == data1[i].attr4) {
                data2.splice(j,1);
            }
        }
    }

data1的长度约为2k,data2的长度约为10k

我知道这个问题大致上已经在这里被问过,但是已经过去了将近2年,而且解决方案使用了外部库。
我只是好奇是否有更好的方法可以使用javascript(或者jQuery或D3,我已经在使用)

谢谢你的帮助!

3个回答

4

也许没有更快,但更易读

const left = ['1', '2', '7']
const right = ['1', '3', '5', '9']

const result = left.filter((x) => !right.includes(x))

如果您需要更复杂的条件进行筛选,可以使用 array.some。附加参考:.includes().some() 的区别。 - Gangula

4

您需要快速查找data1中存在的值,因此使用对象创建一个映射表:

var map = {};
for (var i = 0; i < data1.length; i++) {
  map[data1[i].attr4] = 1;
}

然后您可以循环遍历data2中的项目并进行过滤:
var result = [];
for (i = 0; i < data2.length; i++) {
  if (!(data2[i].attr3 in map)) {
    result.push(data2[i]);
  }
}

好的答案,只是一个提示:如果你必须在整个应用程序中应用这种逻辑来处理数组,你可以看一下underscore。 - jean

3

我想你可以使用Array.filter(参见MDN)或Array.map完成这个任务:

var array1 = [1,2,3,4,5,6,7,8,9],
    array2 = [3,4,5,6],
    fltr   = array1.filter( function(v) {return this.indexOf(v) < 0;}, array2),
    map    = array1.map( 
              function(v) {
                 var exists = this.indexOf(v);
                 return [v, (this[exists] || 'null')].join(', ');}, 
              array2),
    result = document.querySelector('#result');
fltr.unshift('<u>array1</u>');
map.unshift('<u>array1, array2</u>');
result.innerHTML = ['<b>filtered</b>\n',
                     fltr.join('\n'),
                    '\n\n<b>mapped</b>\n',
                     map.join('\n')].join('');
  
<pre id="result"></pre>


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