I'm trying to form a new object in JavaScript based on existing data. I thought it would be a simple task but somehow not.
I want to define the key by year_id and I think this is where it complicates.
Here's my snippet. I tried more pretty solutions as .reduce() but it didn't work so this was an attempt to make it very simple, but it still doesn't work. The resulting object (titles) is just a list of year_id with the values null.
let titles = {}
this.user.titles.forEach(title => {
let key = title.year_id
titles[key] = {}
titles[key].id = title.title.id
titles[key].en = title.title.en
})
return titles
Don't miss understand but the way you asked the question is not very clear. So I am working 'backwards' from the example you have given and guess that the starting data structure which I call 'x' is something like:
var x = [
{title:
{id:"a",en:"b"},
year_id:"c"
},
{title:
{id:"_a",en:"_b"},
year_id:"_c"
}
]
Assuming key values are primitives, year_id is unique, you can still use reduce like below, it looks bulky but it is basically a one liner:
var z = x.map(function(d,i){
var obj = {},
key = d.year_id,
objKey = obj[key]={};
objKey.id = d.title.id,objKey.en = d.title.en;
return obj
})
.reduce(function(ac,d,i){
Object.keys(d).forEach(function(dd,ii){
return ac[dd] = d[dd]
});
return ac
},{})
if you console log z:
{
c : { id : "a", en : "b" },
_c : { id: "_a", en: "_b" }
}
Needless to say this is ES5, no need for babel to transpile.
I don't understand the wording of your question. But from your code example it looks like you're trying to group an array of data by year. Not sure what you're doing with id and en... and I'm assuming year_id is not a unique value.
return this.user.titles.reduce((years, title) => {
const { id, en, year_id } = title;
const yearTitles = years[year_id] || {};
return {
...years,
[year_id]: {
...yearTitles,
[id]: title,
[en]: title,
},
};
}, {});
I think there are two things that might be happening:
let titles = {}
this.user.titles.forEach(title => {
let key = title.year_id
const item = {
id: title.id
en: title.en
}
if(!titles[key]) {
titles[key] = []
}
titles[key].push(item)
})
return titles
If you want to copy all props for a title you can use this instead:
const item = { ...title }
Looks like you're referencing an undefined, namely title.title. You're probably looking to just reference title.id and title.en. delete one of the titles like so:
let titles = {}
this.user.titles.forEach(title => {
let key = title.year_id
titles[key] = {}
titles[key].id = title.id // <-- Changed
titles[key].en = title.en // <-- Changed
})
return titles
EDIT: Then again, maybe I'm mistaken, as title.title.id would throw a TypeError if title.title were undefined, unless title.title exists like so:
{
year_id: 0,
title: "some_title",
id: 0,
en: "en?"
}
In which case title exists, but isn't an object, so no TypeError is thrown.
let title = {};
let existingTitle = {......};
Object.assign(title, existingTitle);
title.id = newID //From where every that may be.
// Do other stuff with the title object.
// Then clear the title object after you've done everything.
title = {};
Be careful, this method has some problems creating a "deep" copy of the existing object. The only true way to get a deep copy is by doing title = JSON.parse(JSON.stringify(existingTitle)). So if the above method doesn't work then use the stringify method. But of course this comes at a price of execution in javascript.
Can you create a working example in codepen or codesandbox? The snippet looks ok. Without seeing the original data may the title.title subpath does not exist? Just guessing, the key seams to exist with a valid value.
Edit: changed the text a bit, after a second closer look into that snippet ๐
Emil Moe
Senior Data Engineer
Emil Moe
Senior Data Engineer
Thanks for the replies. I feel so stupid ๐คช i had the titles connected to a component that constantly changed it value ๐