基于唯一组合将具有对象的数组拆分为多个数组

时间:2017-09-04 19:47:31

标签: javascript

我有这样的数据集:

var dataset = [
{time: "t1", locA: "a1", locB: "b1", value: v1},
{time: "t1", locA: "a1", locB: "b2", value: v2},
{time: "t1", locA: "a2", locB: "b1", value: v3},
{time: "t1", locA: "a2", locB: "b2", value: v4},
{time: "t2", locA: "a1", locB: "b1", value: v5},
{time: "t2", locA: "a1", locB: "b2", value: v6},
{time: "t2", locA: "a2", locB: "b1", value: v7},
{time: "t2", locA: "a2", locB: "b2", value: v8},
....
];

我想要一个这样的结果:

var a1b1 = [ 
{loc: "a1b1", time: "t1", value: "v1"},
{loc: "a1b1", time: "t2", value: "v5"},
....
];
var a1b2 = [ 
{loc: "a1b2", time: "t1", value: "v2"},
{loc: "a1b2", time: "t2", value: "v6"},
....
];
var a2b1 = [ 
{loc: "a2b1", time: "t1", value: "v3"},
{loc: "a2b1", time: "t2", value: "v7"},
....
];
var a2b2 = [ 
{loc: "a2b2", time: "t1", value: "v4"},
{loc: "a2b2", time: "t2", value: "v8"},
....
];

重要的是,t值在表示时间时处于正确的顺序。我不能使用库,只是复古的JavaScript。我发现了一些较旧的SO帖子,它们拆分了一系列对象,但它们描述的只是简单的拆分或使用库。

是否可以使用forEach

dataset.forEach(function()...

感谢任何帮助..

5 个答案:

答案 0 :(得分:2)

另一种简短的Array.prototype.reduce()方法:

var dataset = [
  {time: "t1", locA: "a1", locB: "b1", value: "v1"}, {time: "t1", locA: "a1", locB: "b2", value: "v2"}, {time: "t1", locA: "a2", locB: "b1", value: "v3"}, 
  {time: "t1", locA: "a2", locB: "b2", value: "v4"}, {time: "t2", locA: "a1", locB: "b1", value: "v5"}, {time: "t2", locA: "a1", locB: "b2", value: "v6"}, {time: "t2", locA: "a2", locB: "b1", value: "v7"}, {time: "t2", locA: "a2", locB: "b2", value: "v8"}
];

var result = dataset.reduce(function(r, o){
    var k = o.locA + o.locB;   // unique `loc` key
    if (r[k] || (r[k]=[])) r[k].push({loc:k, time: o.time, value: o.value});
    return r;
}, {});

console.log(result);

答案 1 :(得分:1)

您可以使用reduce对对象进行分组:



function group(arr) {
  return arr.reduce(function(res, obj) {                         // for each object obj in the array arr
    var key = obj.locA + obj.locB;                               // let key be the concatination of locA and locB
    var newObj = {loc: key, time: obj.time, value: obj.value};   // create a new object based on the object obj
    if(res[key])                                                 // if res has a sub-array for the current key then...
      res[key].push(newObj);                                     // ... push newObj into that sub-array
    else                                                         // otherwise...
      res[key] = [ newObj ];                                     // ... create a new sub-array for this key that initially contain newObj
    return res;
  }, {});
}

var result = group([
  {time: "t1", locA: "a1", locB: "b1", value: "v1"},
  {time: "t1", locA: "a1", locB: "b2", value: "v2"},
  {time: "t1", locA: "a2", locB: "b1", value: "v3"},
  {time: "t1", locA: "a2", locB: "b2", value: "v4"},
  {time: "t2", locA: "a1", locB: "b1", value: "v5"},
  {time: "t2", locA: "a1", locB: "b2", value: "v6"},
  {time: "t2", locA: "a2", locB: "b1", value: "v7"},
  {time: "t2", locA: "a2", locB: "b2", value: "v8"}
]);

console.log(result);




注意:而不是将值分配给单独的变量a1b1a1b2,...(它不会非常灵活和动态),而不是回答将结果分组到一个大对象中,该对象包含其等效键下的数组(结果)。所以result是这样的:

result = {
    "a1b1": [ ... ],
    "a1b2": [ ... ],
    ...
}

答案 2 :(得分:1)

这样的东西?



var dataset = [
{time: "t1", locA: "a1", locB: "b1", value: 0},
{time: "t1", locA: "a1", locB: "b2", value: 1},
{time: "t1", locA: "a2", locB: "b1", value: 2},
{time: "t1", locA: "a2", locB: "b2", value: 3},
{time: "t2", locA: "a1", locB: "b1", value: 4},
{time: "t2", locA: "a1", locB: "b2", value: 5},
{time: "t2", locA: "a2", locB: "b1", value: 6},
{time: "t2", locA: "a2", locB: "b2", value: 7}
];

var result = {};

dataset
  .sort((a, b) => { 
    return Number(a.time.replace(/\D/g, '')) > Number(b.time.replace(/\D/g, ''));
  })
  .forEach(d => {
    var key = d.locA + d.locB;

    if (!result[key]) {
      result[key] = [];
    }

    result[key].push({
      loc: key,
      time: d.time,
      value: d.value
    });
  });

console.log(result);




如果你真的想要创建像var a1b1这样的变量而不是结果,请在循环中用result[key]替换window[key]

答案 3 :(得分:0)

使用lodash _.keyBy你可以在key的基础上拆分它。 链接到函数https://lodash.com/docs/4.17.4#keyBy

答案 4 :(得分:0)

我假设值在原始数据集中按时间排序。然后只需要整理数据。

var dataset = [
  {time: "t1", locA: "a1", locB: "b1", value: 'v1'},
  {time: "t1", locA: "a1", locB: "b2", value: 'v2'},
  {time: "t1", locA: "a2", locB: "b1", value: 'v3'},
  {time: "t1", locA: "a2", locB: "b2", value: 'v4'},
  {time: "t2", locA: "a1", locB: "b1", value: 'v5'},
  {time: "t2", locA: "a1", locB: "b2", value: 'v6'},
  {time: "t2", locA: "a2", locB: "b1", value: 'v7'},
  {time: "t2", locA: "a2", locB: "b2", value: 'v8'}
];

// The key for an item is locA joined with locB.
function getItemKey(item) {
  return item.locA + item.locB;
}

// Method for transforming an item into the desired data structure.
function transformItem(item) {
  return {
    loc: getItemKey(item),
    time: item.time,
    value: item.value
  };
}

// Method for collating the dataset so items with a matching locA / locB are grouped together.
function collateLocationData(dataSet) {
  const
    resultMap = new Map();
    
  // Iterate over the data set.
  dataSet.forEach(item => {
    const 
      // Get the key for current item.
      itemKey = getItemKey(item);
    // Check if the key exists in the map...
    if (resultMap.has(itemKey)) {
      // ... and when it does add the transformed item to the key's value.
      resultMap.get(itemKey).push(transformItem(item));
    } else {
      // ... and when it doesn't add the key to the map with the transformed item.
      resultMap.set(itemKey, [transformItem(item)]);
    }
  });
  
  // Return the map.
  return resultMap;
}


const 
  collatedData = collateLocationData(dataset);


/* === LOGGING THE MAP TO THE CONSOLE === */
function itemToString(items) { 
  return items.reduce((html, item) => {
    if (html !== '' ) {
      html += ' || ';
    }
    return html + `loc: ${item.loc} / time: ${item.time} / value: ${item.value}`;
  }, '');
}

collatedData.forEach((values, key) => {
  console.log(`${key} = ${itemToString(values)}`);
});