1

I would like to transform the following array

[{ 0-1s: 6, 1-2s: 2, country: "us" }, { 0-1s: 1, 1-2s: 4, country: "ja" }, { 0-1s: 3, 1-2s: 9, country: "ca" }] 

Into an array like this:

[{ time: "0-1s", us: 6, ja: 1, ca: 3 },{ time: "1-2s", us: 2, ja: 4, ca: 9 }] 

The idea is to pivot my array and make the country fields a new property and the time it took for each country a bucket so no matter how many countries, I only have 2 elements in my array (with as many countries as properties) This is just an example and I have 40+ countries. However, I haven't been able to figure out how can I achieve this new data structure in plan JavaScript.

How should I approach this?

3 Answers 3

3

You could use reduce to group them in to an accumulator object with "0-1s" and "1-2s" as keys. Then use Object.values() to get the array of values:

const input = [{ "0-1s": 6, "1-2s": 2, country: "us" }, { "0-1s": 1, "1-2s": 4, country: "ja" }, { "0-1s": 3, "1-2s": 9, country: "ca" }] const grouped = input.reduce((r, o) => { r["0-1s"] = r["0-1s"] || { time: "0-1s" }; r["1-2s"] = r["1-2s"] || { time: "1-2s" }; r["0-1s"][o.country] = o["0-1s"] r["1-2s"][o.country] = o["1-2s"] return r; }, {}) console.log(Object.values(grouped))

If each object has more dynamic time ranges like 0-1s etc, you could destrcuture the object in the reduce parameter to get the country and rest of the time ranges to separate properties. Loop through the entries of rest to update value for each time range:

const input = [{"0-1s":6,"1-2s":2,country:"us"},{"0-1s":1,"1-2s":4,country:"ja"},{"0-1s":3,"1-2s":9,country:"ca"}]; const grouped = input.reduce((r, { country, ...rest }) => { Object.entries(rest).forEach(([time, v]) => { r[time] = r[time] || { time }; r[time][country] = v }) return r; }, {}) console.log(Object.values(grouped))

Sign up to request clarification or add additional context in comments.

4 Comments

Wow... wasn't aware of the reduce method. This is almost perfect! Would be possible to also include the time as a property afterwards?. I'll mark your answer as accepted once SO allows me
@user3587624 forgot about that. Also, added anothe approach to get the dynmaic number of time range properties
This works like a charm. I really appreciate it. I will continue learning on the reduce method. Looks very powerful!
I liked your second solution alot. Simple fast and efficient. I thought alot but can't get to your approach.
1

Here is a little more dynamic code using reduce(). First get array of unique keys i.e ['0-1s','1-2s'] then convert that to object. Then use reduce() on the arr and add the properties to it.

const arr = [{ '0-1s': 6, '1-2s': 2, country: "us" }, { '0-1s': 1, '1-2s': 4, country: "ja" }, { '0-1s': 3, '1-2s': 9, country: "ca" }] const obj = [...new Set(arr.map(x => Object.keys(x).filter(a => a.includes('-'))).flat())].reduce((ac,a) => (ac[a]=({time:a}),ac),{}); const res = arr.reduce((ac,a) => { Object.keys(a).forEach(x => { if(x.includes('-')) ac[x][a.country] = a[x]; }) return ac; },obj) console.log(Object.values(res))

Comments

0

You can try like this in a modular way (the concept of reusability).

I have used map() method defined on arrays to create new arrays.

Note: You can define keys to stop unnecessary iterations or if your array is huge and most of the keys are matched then no problem.

// function 1 function getNewArray(arr) { let newArr = []; if(arr.length) { let keys = ["0-1s", "1-2s"]; newArr = keys.map((key) => { let newObj = {} // console.log(newObj, key) for(let obj of arr) { if(newObj["time"] === undefined) { newObj["time"] = key } newObj[obj["country"]] =obj[key] } return newObj }) } return newArr } // function 2 function test() { let arr = [{ "0-1s": 6, "1-2s": 2, country: "us" }, { "0-1s": 1, "1-2s": 4, country: "ja" }, { "0-1s": 3, "1-2s": 9, country: "ca" }] let newArr = getNewArray(arr) console.log(newArr) /* [ { time: '0-1s', us: 6, ja: 1, ca: 3 }, { time: '1-2s', us: 2, ja: 4, ca: 9 } ] */ /* --- Pretty printing --- */ console.log(JSON.stringify(newArr, null, 4)) /* [ { "time": "0-1s", "us": 6, "ja": 1, "ca": 3 }, { "time": "1-2s", "us": 2, "ja": 4, "ca": 9 } ] */ } // Start test() 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.