Reputation: 727
I have an array that looks like this:
let movies = [
'terminator.1',
'terminator.2',
'terminator.3',
'harry-potter.1',
'harry-potter.3',
'harry-potter.2',
'star-wars.1'
]
and I would like to have an object like this:
{
"terminator": [1,2,3],
"harry-potter": [1,2,3],
"star-wars": [1]
}
so far I'm able to have an object like this
{
{ terminator: [ '1' ] },
{ terminator: [ '2' ] },
{ terminator: [ '3' ] },
{ 'harry-potter': [ '1' ] },
{ 'harry-potter': [ '3' ] },
{ 'harry-potter': [ '2' ] },
{ 'star-wars': [ '1' ] }
}
I would like to know if there is a way to check during an Array.map when I'm generating my object if there is already a certain key and if there is to push the value to the corresponding array instead of creating a new key-value pair.
This is the code that I currently use for my solution. Thanks in advance.
let movies = [
'terminator.1',
'terminator.2',
'terminator.3',
'harry-potter.1',
'harry-potter.3',
'harry-potter.2',
'star-wars.1'
]
let t = movies.map(m => {
let [name, number] = [m.split('.')[0],m.split('.')[1]]
return {[name]: [number]}
})
console.log(t)
Upvotes: 1
Views: 3121
Reputation: 46
const movies = ['terminator.1', 'terminator.2', 'terminator.3', 'harry-potter.1', 'harry-potter.3', 'harry-potter.2', 'star-wars.1']
const moviesMap = {}
movies.forEach(data => {
const [title, id] = data.split('.')
if (moviesMap[title]) {
moviesMap[title].push(id)
} else {
moviesMap[title] = [id]
}
})
console.log(moviesMap)
Upvotes: 2
Reputation: 31692
That's a job for Array#reduce
, not Array#map
:
let t = movies.reduce((acc, movie) => { // for each movie in movies
let [name, number] = movie.split('.'); // split the movie by "." and store the first part in name and the second in number
if(acc[name]) { // if the accumulator already has an entry for this movie name
acc[name].push(number); // then push this movie number into that entry's array
} else { // otherwise
acc[name] = [number]; // create an entry for this movie name that initially contains this movie number
}
return acc;
}, Object.create(null)); // Object.create(null) is better than just {} as it creates a prototypeless object which means we can do if(acc[name]) safely
Note: If you want to coerce the numbers into actual numbers and not keep them as strings, then use the unary +
to implicitly convert them: +number
.
Example:
let movies = [ 'terminator.1', 'terminator.2', 'terminator.3', 'harry-potter.1', 'harry-potter.3', 'harry-potter.2', 'star-wars.1' ];
let t = movies.reduce((acc, movie) => {
let [name, number] = movie.split(".");
if(acc[name]) {
acc[name].push(number);
} else {
acc[name] = [number];
}
return acc;
}, Object.create(null));
console.log(t);
Upvotes: 1
Reputation: 18515
You can do this with a single Array.reduce
and one array destructuring
in order to get the key/value
combination:
let movies = [ 'terminator.1', 'terminator.2', 'terminator.3', 'harry-potter.1', 'harry-potter.3', 'harry-potter.2', 'star-wars.1' ]
const result = movies.reduce((r,c) => {
let [k,v] = c.split('.')
r[k] = [...r[k] || [], +v]
return r
},{})
console.log(result)
Upvotes: 3