Javascript Optimal way to combine two sets of objects like SQL?

Suppose we have 2 sets of objects

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

We want:

 set3 = set1.join(set2).on('id'); >> set3 [{'id':'1', 'x':'1', 'y':'2', 'z':'1'},{'id':'2', 'x':'2', 'y':'2', 'z':'2'}] 

What are the right tools to achieve this functionality? May underscore help here?

+4
source share
3 answers

OPTION 1 , simple js

I would suggest converting each of the lists into a set by id, for example.

 {1: {x: 1, y: 1}, 2: {x: 2, y: 2}} 

Then run over one (or both) sets and create a new dictionary with the attributes of the two - this last bit depends on whether you are looking for an internal or external connection. This should lead to approximately linear runtime, the implementation of javascript dictionaries is quite effective.

OPTION 2 , underscore, for dense sets of identifiers using _.zip ()

If id relatively dense and you want the outer join to know in advance that the sets of identifiers are the same, another option is to stuff the data into three arrays - one for each attribute and then use the underscore method zip ().

OPTION 3 , underscore using _.groupBy ()

Another opportunity to run _.groupBy () on lists that you have is using a special comparison method, which will also allow you to connect to multiple keys. However, simple post-processing will be required since the direct result will be a dictionary of the word

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

The internal behavior of the connection in the latter case can be achieved by filtering these elements in the resulting dictionary that do not have the maximum number of elements in the list (2, in the example).

+3
source

OPTION 4: Alasql library

Alasql can join two tables in an "SQL manner" .:

 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]); 

It gives exactly what you need:

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

Try this example in jsFiddle .

+3
source

Another option using 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) }) 

assumptions

  //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 

Output

  [{ ...set1 members... , relationName: ...set2 members... }] 

I think a better result might be (it shouldn't be hard to get here):

  [{ , leftObj:...set1 members... , rightObj: ...set2 members... }] 

and add support for internal joins. But I replaced some crappy code and needed to replicate the hierarchy of objects.

+1
source

All Articles