根据分组属性连接2个对象数组

时间:2017-11-13 14:52:49

标签: javascript arrays algorithm object group-by

使用以下JSON API响应:

{
   "default" : [
      {"val_a" : 5 , "val_b": 10, "key_a":"A", "key_b":"X"},
      {"val_a" : 15 , "val_b": 11, "key_a":"A", "key_b":"Y"},
      {"val_a" : 6 , "val_b": 12, "key_a":"B", "key_b":"Z"}
   ],
   "alt" : [
      {"val_a" : 15 , "val_b": 11, "key_a":"A", "key_b":"Y"},
      {"val_a" : 9 , "val_b": 10, "key_a":"A", "key_b":"X"}
   ]
}

我试图编写一个合并函数,它会产生以下结果:

[
 {"alt_val_a":9, "alt_val_b":10 ,"val_a" : 5 , "val_b": 10, "key_a":"A", "key_b":"X"},
 {"alt_val_a":15, "alt_val_b":11 ,"val_a" : 15 , "val_b": 11, "key_a":"A", "key_b":"Y"},
 {"val_a" : 6 , "val_b": 12, "key_a":"B", "key_b":"Z"}
]

解释
结果基于2个属性合并," key_a" " key_b"产生独特的入门组合。 " alt"前缀被添加到其他属性。

编辑:上述示例中的分组键(key_b,key_a)是根据对api 的请求动态更改,因此另一个API响应可能有另一个分组涉及的密钥,例如key_c,因此该函数应该足够通用,以便将分组密钥作为数组接受。

编辑2 为了说清楚,val_a和val_b只是特定响应的一个示例。在另一个响应中,val_c可能存在或者val_a可能丢失。

我正在考虑一个接受原始JSON和按键分组的函数 像这样:

function transformResults(results,groupings){
   //...
}

用法:

transformResults(originalJSON,["key_a","key_b"]);

感谢任何帮助:)

2 个答案:

答案 0 :(得分:1)

您可以迭代原始结果,并根据组键创建一个新的对象,如下所示:

{ AX: 
   { val_a: 5,
     val_b: 10,
     key_a: 'A',
     key_b: 'X',
     alt_val_a: 9,
     alt_val_b: 10 },
  AY: 
   { val_a: 15,
     val_b: 11,
     key_a: 'A',
     key_b: 'Y',
     alt_val_a: 15,
     alt_val_b: 11 },
  BZ: { val_a: 6, val_b: 12, key_a: 'B', key_b: 'Z' } }

然后将键映射到最终数组 这是我的通用版本:



function transformResults(results, groupings) {
  let reducedResults = Object.keys(results).reduce((modified, originalKey) => {
    //iterating over the original results
    results[originalKey].forEach((row) => {
      //creating a dynamic key based on the grouping key values
      let groupKey = groupings.reduce((resultKey, keyVal) => {
        resultKey = resultKey + row[keyVal];
        return resultKey;
      }, "");

      //iterating over each row values
      Object.keys(row).forEach((rowKey) => {
        //determine if a prefix should be added to the original row key
        let finalKey = (originalKey === 'default' || groupings.indexOf(rowKey) !== -1) ? rowKey : originalKey + "_" + rowKey;
        //creating a modified object where the key is the unique group value
        modified[groupKey] = modified[groupKey] || {};
        modified[groupKey][finalKey] = row[rowKey];
      });
    });
    return modified;
  }, {});

  //mapping the object results and modifying the results to an array
  return Object.keys(reducedResults).map((gKey) => {
    return reducedResults[gKey];
  });
}

let data = {
  "default": [
    {"val_a": 5, "val_b": 10, "key_a": "A", "key_b": "X"},
    {"val_a": 15, "val_b": 11, "key_a": "A", "key_b": "Y"},
    {"val_a": 6, "val_b": 12, "key_a": "B", "key_b": "Z"}
  ],
  "alt": [
    {"val_a": 15, "val_b": 11, "key_a": "A", "key_b": "Y"},
    {"val_a": 9, "val_b": 10, "key_a": "A", "key_b": "X"}
  ]
};

console.log(transformResults(data, ["key_a", "key_b"]));




答案 1 :(得分:0)

您可以为同一组使用哈希表。

此提案会改变原始对象。

function transformResults(object, keys) {
    var getValues = function (o) { return function (k) { return o[k]; }; },
        hash = Object.create(null),
        result = object.default.map(function (o) {
            var key = keys.map(getValues(o)).join('|');
            return hash[key] = o;
        });

    object.alt.forEach(function (o) {
        var key = keys.map(getValues(o)).join('|');
        if (!hash[key]) {
            result.push(hash[key] = {});
            keys.forEach(function (k) {
                hash[key][k] = o[k];
            });
        }
        Object.keys(o).forEach(function (k) {
            if (keys.indexOf(k) === -1) {
                return;
            }
            hash[key]['alt_' + k] = o[k];
        });
    });
    return result;
}

var object = { default: [{ val_a: 5, val_b: 10, key_a: "A", key_b: "X" }, { val_a: 15, val_b: 11, key_a: "A", key_b: "Y" }, { val_a: 6, val_b: 12, key_a: "B", key_b: "Z" }], alt: [{ val_a: 15, val_b: 11, key_a: "A", key_b: "Y" }, { val_a: 9, val_b: 10, key_a: "A", key_b: "X" }, { val_a: 9, val_b: 10, key_a: "C", key_b: "X" }] };

console.log(transformResults(object, ["key_a", "key_b"]));
.as-console-wrapper { max-height: 100% !important; top: 0; }