Javascript。连接两组对象(如SQL)的最佳方法?

Javascript。连接两组对象(如SQL)的最佳方法?,javascript,underscore.js,Javascript,Underscore.js,假设我们有两组对象 set1 = [{'id':'1', 'x':'1', 'y':'2'}, {'id':'2', 'x':'2', 'y':'2'}] set2 = [{'id':'1', 'z':'1'}, {'id':'2', 'z':'2'}] 我们希望: set3 = set1.join(set2).on('id'); >> set3 [{'id':'1', 'x':'1', 'y':'2', 'z':'1'},{'id':'2', 'x':'2', 'y':'2

假设我们有两组对象

set1 = [{'id':'1', 'x':'1', 'y':'2'}, {'id':'2', 'x':'2', 'y':'2'}]
set2 = [{'id':'1', 'z':'1'}, {'id':'2', 'z':'2'}]
我们希望:

set3 = set1.join(set2).on('id'); 

>> set3 
[{'id':'1', 'x':'1', 'y':'2', 'z':'1'},{'id':'2', 'x':'2', 'y':'2', 'z':'2'}]
实现此功能的正确工具是什么?
我可以帮忙吗

选项1,普通js

我建议您将每个列表转换为一组id,例如

{1: {x: 1, y: 1}, 2: {x: 2, y: 2}}
然后对其中一个(或两个)集合运行一个,并使用这两个集合中的属性创建一个新字典——后一位取决于您是在寻找内部联接还是外部联接。这将导致大致线性的运行时,字典的javascript实现非常高效

选项2,下划线,用于密集id集,使用uz.zip()

如果
id
相对密集,并且您希望外部联接或事先知道id集完全相同,另一个选项是将数据填充到三个数组中——每个属性一个数组,然后使用下划线的zip()方法

选项3,下划线,使用u.groupBy()

中的另一种可能性是使用自定义比较方法在列表上运行u.groupBy(),这也允许在多个键上进行连接。不过,需要一些简单的后处理,因为直接结果将是表单的字典

{1: [{'id':'1', 'x':'1', 'y':'2'}, {'id':'1', 'z':'1'}],
 2: [{'id':'2', 'x':'2', 'y':'2'}, {'id':'2', 'z':'2'}]}
在后一种情况下,可以通过过滤掉结果字典中列表中没有最大项数的项(示例中为2项)来实现内部联接行为。

选项4:库

Alasql可以以“SQL方式”连接两个表:

var set1 = [{'id':'1', 'x':'1', 'y':'2'}, {'id':'2', 'x':'2', 'y':'2'}];
var set2 = [{'id':'1', 'z':'1'}, {'id':'2', 'z':'2'}];

var res = alasql('SELECT * FROM ? set1 JOIN ? set2 USING id',[set1, set2]);
它提供了您所需要的:

[{"z":"1","id":"1","x":"1","y":"2"},{"z":"2","id":"2","x":"2","y":"2"}]

试试。

使用Ramda的另一个选项:

const r = require('ramda')
const outerJoin = r.curry(function(relationName, set1, keyName1, set2, keyName2) {
    const processRecord = function(record1) {
        const key1 = record1[keyName1]
        const findIn2 = r.find(r.propEq(keyName2, key1))
        const record2 = findIn2(set2)
        record1[relationName] = record2
        return record1
    }
    return r.map(processRecord, set1)
})
假设

  //set1 is an array of objects
  set1 : [{}]
  //set1 has a property for the key of type T
  set1[keyName1] : T
  //set2 is an array of objects
  set2 : [{}]
  //set2 has a property for the key which is also of type T
  set2[keyName2] : T
输出

 [{
     ...set1 members...
     , relationName: ...set2 members...
  }]
我想更好的输出可能是(在这里应该不难获得):


并添加对内部联接的支持。但是我替换了一些蹩脚的代码,需要复制对象层次结构。

我正在寻找内部连接,而且有可能在2个或更多字段上连接也很好。JSFIDLE示例不再工作:
ReferenceError:ALAQ未定义
~*~我可以通过简单地将
添加到HTML代码中,轻松地使其再次工作。我很想把这个答案放在一个堆栈片段中。不幸的是,它只会导致
“SecurityError:操作不安全。”
“ReferenceError:未定义alasql”
-要查看它的外观,请尝试运行例如的第一个片段。~*~不管出于什么原因,堆栈交换(代码片段)似乎认为AlaSQL存在安全问题,而JSFIDLE没有这样的问题使用
https://cdn.jsdelivr.net/npm/alasql@1.7.2
也没有帮助。
 [{
     , leftObj:...set1 members...
     , rightObj: ...set2 members...
  }]