在具有不同值的对象数组中查找对象的最有效方法是什么?
What would be the most efficient way to find an object in an array of objects with distinct value which is an array?
我最初在几个月前的一次采访中遇到了这个问题,现在已经解决了。
所以我们有这个对象数组,目标是找到一个对象,其中的演员没有在电影中出现超过一次。所以基本上找一部有独特演员的电影。
[
{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
]
我为自己设定的目标是使用函数式方法解决它,因此我们自然需要清除没有 bestScene
的对象,如下所示:
const moviesWithActorsPresent = movies.filter((movie) => movie.bestScene)
然后我可以使用 reduce
构造一个对象数组,如下所示:
[
{ 'The Dark Knight': [ 'Christian Bale', 'Tom Hardy' ] },
{ 'Good Burger': [ 'Kenan Thompson', 'Kel Mitchell' ] },
{ 'The Big Short': [ 'Christian Bale', 'Steve Carrell' ] }
]
然后使用 for
或 forEach
循环并在临时变量中跟踪演员,但对我来说这并不是一个完美的解决方案。
我们可以在这里使用什么CS概念来有效地解决它?
获得 moviesWithActorsPresent
后,创建一个对象(或地图)来计算整个数组中每个演员的出现次数。然后你可以 .find
一个对象,其中 .every
actor 的计数恰好为 1:
const movies =[
{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
];
const moviesWithActorsPresent = movies.filter((movie) => movie.bestScene)
const actorCounts = moviesWithActorsPresent.reduce((a, { bestScene }) => {
const { actors } = bestScene;
return Object.assign(
{}, // don't mutate
a, // prior counts
...actors.map(actor => ({ [actor]: (a[actor] || 0) + 1 }))
);
}, {});
const movieWithUniqueActors = moviesWithActorsPresent.find(({ bestScene }) => (
bestScene.actors.every(actor => actorCounts[actor] === 1)
));
console.log(movieWithUniqueActors);
几乎肯定没关系,但如果需要,您可以将 .filter
功能放入 .reduce
:
const movies = [{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
];
const actorCounts = movies.reduce((a, { bestScene }) => {
if (!bestScene) {
return a;
}
const { actors } = bestScene;
return Object.assign({}, // don't mutate
a, // prior counts
...actors.map(actor => ({
[actor]: (a[actor] || 0) + 1
}))
);
}, {});
const movieWithUniqueActors = movies.find(({ bestScene }) => (
bestScene.actors.every(actor => actorCounts[actor] === 1)
));
console.log(movieWithUniqueActors);
您只需要创建一个将 films by actors
分组的函数,然后只获取那些具有 1
胶片的函数。
const group = (data) => data
.reduce((res, { name, bestScene }) => {
((bestScene || {}).actors || []).forEach(actor => {
res[actor] = (res[actor] || []).concat(name);
});
return res;
}, {});
const solve = data => Object
.entries(group(data))
.filter(([author, films]) => films.length === 1)
const data = [
{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
];
console.log(solve(data));
我最初在几个月前的一次采访中遇到了这个问题,现在已经解决了。
所以我们有这个对象数组,目标是找到一个对象,其中的演员没有在电影中出现超过一次。所以基本上找一部有独特演员的电影。
[
{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
]
我为自己设定的目标是使用函数式方法解决它,因此我们自然需要清除没有 bestScene
的对象,如下所示:
const moviesWithActorsPresent = movies.filter((movie) => movie.bestScene)
然后我可以使用 reduce
构造一个对象数组,如下所示:
[
{ 'The Dark Knight': [ 'Christian Bale', 'Tom Hardy' ] },
{ 'Good Burger': [ 'Kenan Thompson', 'Kel Mitchell' ] },
{ 'The Big Short': [ 'Christian Bale', 'Steve Carrell' ] }
]
然后使用 for
或 forEach
循环并在临时变量中跟踪演员,但对我来说这并不是一个完美的解决方案。
我们可以在这里使用什么CS概念来有效地解决它?
获得 moviesWithActorsPresent
后,创建一个对象(或地图)来计算整个数组中每个演员的出现次数。然后你可以 .find
一个对象,其中 .every
actor 的计数恰好为 1:
const movies =[
{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
];
const moviesWithActorsPresent = movies.filter((movie) => movie.bestScene)
const actorCounts = moviesWithActorsPresent.reduce((a, { bestScene }) => {
const { actors } = bestScene;
return Object.assign(
{}, // don't mutate
a, // prior counts
...actors.map(actor => ({ [actor]: (a[actor] || 0) + 1 }))
);
}, {});
const movieWithUniqueActors = moviesWithActorsPresent.find(({ bestScene }) => (
bestScene.actors.every(actor => actorCounts[actor] === 1)
));
console.log(movieWithUniqueActors);
几乎肯定没关系,但如果需要,您可以将 .filter
功能放入 .reduce
:
const movies = [{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
];
const actorCounts = movies.reduce((a, { bestScene }) => {
if (!bestScene) {
return a;
}
const { actors } = bestScene;
return Object.assign({}, // don't mutate
a, // prior counts
...actors.map(actor => ({
[actor]: (a[actor] || 0) + 1
}))
);
}, {});
const movieWithUniqueActors = movies.find(({ bestScene }) => (
bestScene.actors.every(actor => actorCounts[actor] === 1)
));
console.log(movieWithUniqueActors);
您只需要创建一个将 films by actors
分组的函数,然后只获取那些具有 1
胶片的函数。
const group = (data) => data
.reduce((res, { name, bestScene }) => {
((bestScene || {}).actors || []).forEach(actor => {
res[actor] = (res[actor] || []).concat(name);
});
return res;
}, {});
const solve = data => Object
.entries(group(data))
.filter(([author, films]) => films.length === 1)
const data = [
{
name: 'The Dark Knight',
rating: 'PG-13',
year: 2012,
bestScene: {
name: 'fight',
location: 'sewer',
sceneLength: 10,
actors: ['Christian Bale', 'Tom Hardy']
}
},
{
name: 'Good Burger',
rating: 'PG',
year: 1994,
bestScene: {
name: 'jump',
location: 'giant milkshake',
sceneLength: 5,
actors: ['Kenan Thompson', 'Kel Mitchell']
}
},
{
name: 'Sharknado 2: The Second One',
rating: 'TV-14',
year: 2013
},
{
name: 'The Big Short',
rating: 'R',
year: 2015,
bestScene: {
name: 'explanation',
location: 'casino',
sceneLength: 20,
actors: ['Christian Bale', 'Steve Carrell']
}
}
];
console.log(solve(data));