最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Split array with objects to multiple arrays based on unique combination - Stack Overflow

programmeradmin3浏览0评论

I have a dataset like this:

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},
....
];

I want a result like this:

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"},
....
];

It's important that the t values are in the correct order while it represents time. I cannot use libraries, just vintage JavaScript. I found some older SO posts with splitting an array of objects but they describe just simple splitting or using libraries.

Is it possible with forEach like

dataset.forEach(function()...

Any help is appreciated..

I have a dataset like this:

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},
....
];

I want a result like this:

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"},
....
];

It's important that the t values are in the correct order while it represents time. I cannot use libraries, just vintage JavaScript. I found some older SO posts with splitting an array of objects but they describe just simple splitting or using libraries.

Is it possible with forEach like

dataset.forEach(function()...

Any help is appreciated..

Share Improve this question asked Sep 4, 2017 at 19:47 3TW33TW3 3371 gold badge3 silver badges14 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 7

Another short Array.prototype.reduce() approach:

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

You can use reduce to group the objects:

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

Note: Instead of assigning the values to separate variables a1b1, a1b2, ... (which won't be very flexible and dynamic), my answer groups the results into one big object that contain the arrays (results) under their equivalent keys. So result is like this:

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

Something like this?

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

If you really want to create vars like var a1b1 instead of an object as result, replace result[key] with window[key] inside the loop.

using lodash _.keyBy you can split it on the bases of key. link to the function https://lodash./docs/4.17.4#keyBy .

I assumed the values are ordered by time in the original data set. Then it is just a matter of collating the data.

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)}`);
});

发布评论

评论列表(0)

  1. 暂无评论