简体   繁体   English

Javascript:使用一个键对对象数组进行完全外连接

[英]Javascript: Full Outer Join on a Array of Objects, using one key

I have two arrays of objects which I want to "Full Outer Join", like in SQL:我有两个对象数组,我想“完全外连接”,就像在 SQL 中一样:

Dataset A:数据集 A:

[ { id: 1, name: "apple", color: "red" }, {id: 2, name: "banana", color: "yellow"} ]

Dataset B:数据集 B:

[ { id: 1, name: "apple", color: "blue" }, {id: 3, name: "mango", color: "green"} ]

Intended result:预期结果:

[ { id: 1, dataset_a: { id: 1, name: "apple", color: "red" }
         , dataset_b: { id: 1, name: "apple", color: "blue" }
  }
, { id: 2, dataset_a: { id: 2, name: "banana", color: "yellow"}
         , dataset_b: null
  }
, { id: 3, dataset_a: null
         , dataset_b: { id: 3, name: "mango", color: "green"}
  }
]
  • The id's are unique. id 是唯一的。
  • Lodash may be used.可以使用 Lodash。
  • I have no restriction on ES version.我对 ES 版本没有限制。

Instead of null, an empty object would be OK too.而不是 null,一个空对象也可以。 The id's don't necessarily need to be repeated, as shown below. id不一定要重复,如下图。 So, this would be just as good:所以,这同样好:

[ { id: 1, dataset_a: { name: "apple", color: "red" }
         , dataset_b: { name: "apple", color: "blue" }
  }
, { id: 2, dataset_a: { name: "banana", color: "yellow"}
         , dataset_b: {}
  }
, { id: 3, dataset_a: {}
         , dataset_b: { name: "mango", color: "green"}
  }
]

Nina Scholtz solution, transformed into aa function: Nina Scholtz 解,转化为 aa 函数:

fullOuterJoin(dataset_a_name, dataset_b_name, dataset_a, dataset_b, key) {
    const getNullProperties = keys => Object.fromEntries(keys.map(k => [k, null]));
    var data = { [dataset_a_name]:dataset_a, [dataset_b_name]:dataset_b },
        result = Object
            .entries(data)
            .reduce((r, [table, rows]) => {
                //forEach dynamic destructuring
                rows.forEach(({ [key]:id, ...row }) => {
                    if (!r[id]) r.items.push(r[id] = { [key]:id, ...getNullProperties(r.tables) });
                    r[id][table] = row;
                });
                r.tables.push(table);
                r.items.forEach(item => r.tables.forEach(t => item[t] = item[t] || null));
                return r;
            }, { tables: [], items: [] })
            .items;

    return result;
},

A code snippet for specifically your need:专门满足您需求的代码片段:

const datasetA = [ { id: 1, name: "apple", color: "red" }, {id: 2, name: "banana", color: "yellow"} ]
const datasetB = [ { id: 1, name: "apple", color: "blue" }, {id: 3, name: "mango", color: "green"} ]


const joined = [];

// datasetA
for (let i = 0; i < datasetA.length; i++) {
    let item = {
        id: datasetA[i].id,
        dataset_a: datasetA[i],
    };
    joined.push(item);
}
// datasetB
for (let i = 0; i < datasetB.length; i++) {
    const foundObject = joined.find(d => d.id === datasetB[i].id);
    if (foundObject) {
        foundObject['dataset_b'] = datasetB[i];
    }
    else {
        let item = {
            id: datasetB[i].id,
            dataset_a: {},
            dataset_b: datasetB[i],
        };
        joined.push(item);
    }
}

console.log(joined);

You could take a dynamic approach and store the wanted data sets in an object and iterate the entries form the object.您可以采用动态方法并将所需的数据集存储在对象中,然后从对象中迭代条目。 Then group by id and get all items back.然后按id分组并取回所有项目。

This approach uses an object as hash table with id as key and an array as storage for the result set.这种方法使用对象作为哈希表,以id作为键,使用数组作为结果集的存储。 If an id is not known, a new object with id and previously used keys with null value are used.如果id未知,则使用具有id的新对象和先前使用的具有null值的键。 Then the actual data set is added to the object.然后将实际数据集添加到对象中。

Finally for missing tables null values are assigned as well.最后,对于缺少的表, null值也被分配。

 const getNullProperties = keys => Object.fromEntries(keys.map(k => [k, null])); var dataset_a = [{ id: 1, name: "apple", color: "red" }, { id: 2, name: "banana", color: "yellow" }], dataset_b = [{ id: 1, name: "apple", color: "blue" }, { id: 3, name: "mango", color: "green" }], data = { dataset_a, dataset_b }, result = Object .entries(data) .reduce((r, [table, rows]) => { rows.forEach(({ id, ...row }) => { if (!r[id]) r.items.push(r[id] = { id, ...getNullProperties(r.tables) }); r[id][table] = row; }); r.tables.push(table); r.items.forEach(item => r.tables.forEach(t => item[t] = item[t] || null)); return r; }, { tables: [], items: [] }) .items; console.log(result);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

var array1 = [ { id: 1, name: "apple", color: "red" }, {id: 2, name: "banana", color: "yellow"} ]
var array2 = [ { id: 1, name: "apple", color: "blue" }, {id: 3, name: "mango", color: "green"} ]

var array_sum = array1.concat(array2)

var array_result = []

array_sum.forEach(function(candidate, index){
  var obj_id = candidate.id;
  delete candidate.id
  if(array_result.length == 0){
    array_result.push({
      "id": obj_id,
      ["dataset_" + index]: candidate
    })
  }else{
    for(var i=0; i<array_result.length; i++){
      if(array_result[i].id == obj_id){
        array_result[i]["dataset_" + index] = candidate
        break;
      }else if(i == array_result.length - 1){
        array_result.push({
          "id": obj_id,
          ["dataset_" + index]: candidate
        })
      }
    }
  }
})
console.log(array_result)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM