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 badges5 Answers
Reset to default 7Another 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)}`);
});