Reputation: 95
So I have an object:
var data = {
"movies": {
"first": {
"title": "Bruce Almigthy",
"actors": ["Jim Carrey", "Morgan Freeman", "Jennifer Aniston"],
"year": "2003"
},
"second": {
"title": "The Truman Show",
"actors": ["Jim Carrey", "Ed Harris","Morgan Freeman", "Laura Linney"],
"year": "1998"
},
"third": {
"title": "Ace Ventura",
"actors": ["Jim Carrey", "Courteney Cox","Ed Harris"],
"year": "1994"
}
}
};
console.log(data.movies);
And I need to find actors that stared in 1+ movies, and actors that starred only in one movie. I usually handle this type of problem with something like this:
function countMax(data) {
var actors = {};
Object.keys(data.movies).forEach(function (key) {
var movie = data.movies[key];
movie.actors.forEach(function (actor) {
if (!actors.hasOwnProperty(actor)) actors[actor] = 0;
actors[actor]++;
})
})
Object.keys(actors).forEach(function (actor) {
var count = actors[actor];
if (count > 1) console.log(actor + ' stars in ' + count + ' movies.');
});
};
countMax(data);
I am wondering if there is a different way of doing this, maybe by using regex or something like that? I am just not sure how would I "approach" to the object.
Upvotes: 0
Views: 172
Reputation:
I think I'd refactor it a bit.
var data = {"movies":{"first":{"title":"Bruce Almigthy","actors":["Jim Carrey","Morgan Freeman","Jennifer Aniston"],"year":"2003"},"second":{"title":"The Truman Show","actors":["Jim Carrey","Ed Harris","Morgan Freeman","Laura Linney"],"year":"1998"},"third":{"title":"Ace Ventura","actors":["Jim Carrey","Courteney Cox","Ed Harris"],"year":"1994"}}};
function countMax(data) {
Array.from(Object.values(data.movies).reduce((m, movie) => {
movie.actors.forEach(actor => m.set(actor, (m.get(actor) || 0) + 1));
return m;
}, new Map()).entries())
.filter(([_, count]) => count > 1)
.forEach(([actor, count]) => console.log(actor + ' stars in ' + count + ' movies.'))
}
countMax(data);
Upvotes: 0
Reputation: 24181
What you have done seems fine, regex is not a magic wand to solve all problems.
Here I've just modified what you have done using a bit more ES6 sugar. Like Object.values
& Object.entries
ps. hasOwnProperty
is not required, you needed it in ES5 when using for in
, ps. for of
can be used nowadays..
const data = {
"movies": {
"first": {
"title": "Bruce Almigthy",
"actors": ["Jim Carrey", "Morgan Freeman", "Jennifer Aniston"],
"year": "2003"
},
"second": {
"title": "The Truman Show",
"actors": ["Jim Carrey", "Ed Harris","Morgan Freeman", "Laura Linney"],
"year": "1998"
},
"third": {
"title": "Ace Ventura",
"actors": ["Jim Carrey", "Courteney Cox","Ed Harris"],
"year": "1994"
}
}
};
function countMax(data) {
var actors = {};
Object.values(data.movies).forEach(movie =>
movie.actors.forEach(actor => actors[actor] = (actors[actor] | 0) + 1)
)
Object.entries(actors).forEach(([actor, count]) => {
if (count > 1) console.log(actor + ' stars in ' + count + ' movies.');
});
};
countMax(data);
Upvotes: 0
Reputation: 92440
I don't think there's much a regex will do for you here, but you can shorten things a bit with some of the niceties of modern Javascript. For example you can make a map of the actors and counts with:
var actor_map = Object.values(data.movies).reduce((a, c) => {
c.actors.forEach(i => a[i] = a[i] ? a[i]+1 : 1 )
return a
}, {})
Then you can filter for the counts to get whatever you want:
var more_that_one = Object.entries(actor_map).filter(([k, v]) => v > 1)
var less_that_one = Object.entries(actor_map).filter(([k, v]) => v == 1)
var data = {
"movies": {
"first": {
"title": "Bruce Almigthy",
"actors": ["Jim Carrey", "Morgan Freeman", "Jennifer Aniston"],
"year": "2003"
},
"second": {
"title": "The Truman Show",
"actors": ["Jim Carrey", "Ed Harris","Morgan Freeman", "Laura Linney"],
"year": "1998"
},
"third": {
"title": "Ace Ventura",
"actors": ["Jim Carrey", "Courteney Cox","Ed Harris"],
"year": "1994"
}
}
};
var actor_map = Object.values(data.movies).reduce((a, c) => {
c.actors.forEach(i => a[i] = a[i] ? a[i]+1 : 1 )
return a
}, {})
var more_that_one = Object.entries(actor_map).filter(([k, v]) => v > 1)
var less_that_one = Object.entries(actor_map).filter(([k, v]) => v == 1)
console.log(more_that_one)
console.log(less_that_one)
Upvotes: 1