Reputation: 680
I have an object like this that I get from an external endpoint so cannot change:
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
}
I need to get it into a format like:
1: {
1: { "time": 1, "day": 1 },
2: { "time": 2, "day": 1 },
3: { "time": 3, "day": 1 },
},
2: {
1: { "time": 1, "day": 2 },
2: { "time": 2, "day": 2 },
3: { "time": 3, "day": 2 },
}
Where the first key is the day, and the second is the time.
My attempt doesn't work
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
}
let test = {}
let defaultRow = {
1: {},
2: {}
}
Object.keys(obj).forEach((key) => {
if (!test[obj[key]["day"]]) {test[obj[key]["day"]] = defaultRow}
test[obj[key]["day"]][obj[key]["time"]] = obj[key]
})
console.log(test)
Both days contain the same data for some reason. How can I achieve this? Any help is appreciated!
Upvotes: 1
Views: 156
Reputation: 177685
My rather readable version
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
}
let test = {}
for (let o in obj) {
const day = obj[o].day;
const time = obj[o].time;
if (test[day]==undefined) {
test[day] = {}
}
test[day][time] = {day:day,time:time}
}
console.log(test)
Upvotes: -1
Reputation: 191916
Convert into an array of object using Object#values, and iterate the array using Array#reduce to convert to the desired format.
const obj = {"0":{"time":1,"day":1},"1":{"time":2,"day":1},"2":{"time":3,"day":1},"3":{"time":1,"day":2},"4":{"time":2,"day":2},"5":{"time":3,"day":2}};
const result = Object.values(obj).reduce((r, o) => {
r[o.day] = Object.assign(r[o.day] || {}, { [o.time]: o });
return r;
}, {});
console.log(result);
Upvotes: 0
Reputation: 2367
I don't really know why you need an object with properties 1...n instead of just using arrays for this purpose. I would solve it like this:
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
};
function orderByDay(obj){
const result = {};
Object.keys(obj).forEach(function(key){
let day = obj[key].day;
if(result.hasOwnProperty(day)){
result[day].push(obj[key]);
}else{
result[day] = [obj[key]];
}
});
return result;
}
console.log(orderByDay(obj));
Upvotes: 0
Reputation: 10458
// your code goes here
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
}
obj = Object.values(obj).reduce(function(newObject, val){
//console.log(val.day, val.time, newObject);
if(newObject[val['day']] == undefined)
newObject[val['day']] ={};
newObject[val['day']][val['time']] = val;
//console.log(val.day, val.time, newObject);
return newObject;
},{})
console.log(obj);
/*
output
{ '1':
{ '1': { time: 1, day: 1 },
'2': { time: 2, day: 1 },
'3': { time: 3, day: 1 } },
'2':
{ '1': { time: 1, day: 2 },
'2': { time: 2, day: 2 },
'3': { time: 3, day: 2 } } }
*/
Upvotes: 0
Reputation: 847
There is start with :
const result = Object.values(obj).reduce((accumulator, currentValue) => {
if (!accumulator[currentValue.day]) accumulator[currentValue.day] = []
accumulator[currentValue.day].push(currentValue)
return accumulator
}, {})
console.log(result)
This is not THE solution but a starting kit :)
More infos: - MDN reduce - Stackoverflow search
Upvotes: 0
Reputation: 537
This will work for you
var result = Object.values(obj).reduce((count, currentValue) => {
count[currentValue.day] = count[currentValue.day] || {};
count[currentValue.day][Object.keys(count[currentValue.day]).length + 1] = currentValue;
return count
}, {});
Upvotes: 0
Reputation: 386522
You could take the objects and build a new object with a new structure.
var object = { 0: { time: 1, day: 1 }, 1: { time: 2, day: 1 }, 2: { time: 3, day: 1 }, 3: { time: 1, day: 2 }, 4: { time: 2, day: 2 }, 5: { time: 3, day: 2 } },
result = Object.values(object).reduce(
(r, o) => ((r[o.day] = r[o.day] || {})[o.time] = o, r),
{}
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 2753
To solve this problem, you need to iterate through your object and make value
of day
as your outer and increment the inner key
as per the number of keys in the Object which you can get by Object.keys.length
.
Here is the sample code.
let obj = {
0: {
"time": 1,
"day": 1,
},
1: {
"time": 2,
"day": 1,
},
2: {
"time": 3,
"day": 1,
},
3: {
"time": 1,
"day": 2,
},
4: {
"time": 2,
"day": 2,
},
5: {
"time": 3,
"day": 2,
}
}
let newObj = {};
for (let key in obj) {
if(typeof newObj[obj[key]["day"]] !== "object") {
newObj[obj[key]["day"]] = {};
}
let index = Object.keys(newObj[obj[key]["day"]]).length + 1;
newObj[obj[key]["day"]][index] = obj[key];
}
console.log(newObj);
Upvotes: 0
Reputation: 171679
Both days contain the same data for some reason
Because you assign the same object reference defaultRow
to each row. A simple fix is turn defaultRow
into a function that returns a new object each time
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
}
let test = {}
let defaultRow = function() {
return {
1: {},
2: {}
}
}
Object.keys(obj).forEach((key) => {
if (!test[obj[key]["day"]]) {
test[obj[key]["day"]] = defaultRow();
}
test[obj[key]["day"]][obj[key]["time"]] = obj[key]
})
console.log(test)
Simple example of the problem
var obj ={a:1},
foo = obj,
bar = obj;
foo.a=2;
console.log(bar.a) //returns 2 because is same object as foo
Upvotes: 2
Reputation: 45121
Since you want your nested objects to be plain objects not arrays the solution to get last index is rather involved.
let obj = {
0: { "time": 1, "day": 1, },
1: { "time": 2, "day": 1, },
2: { "time": 3, "day": 1, },
3: { "time": 1, "day": 2, },
4: { "time": 2, "day": 2, },
5: { "time": 3, "day": 2, }
}
console.log(
Object.values(obj).reduce(
(acc, value) => {
const holder = acc[value.day] || (acc[value.day] = { })
const keys = Object.keys(holder).map(key => +key)
holder[keys.length ? (Math.max(...keys) + 1) : 1] = value
return acc
},
{}
)
)
Upvotes: 0