Вот одна из техник: сворачивание профилей, захват mov ie и имен людей внутри параметров, а затем просто запись нового аккумулятора с этими данными. Обратите внимание, что при этом возникает потенциальная проблема с производительностью, как описано в отличной статье Rich Snapp . Если это вызывает у вас реальную проблему, достаточно легко изменить это, чтобы изменить аккумулятор.
Я добавил некоторые дополнительные данные, чтобы показать, что происходит, когда пользователь или mov ie отсутствуют в соответствующих списках . Если этого никогда не произойдет, вы можете немного упростить объявления name
и person
. Но я бы не рекомендовал это, поскольку вещи, которые "никогда не могут случиться", на самом деле происходят регулярно.
const groupNamesByMovie = (profiles, users, movies) =>
profiles .reduce ((
a, {userID, favoriteMovieID}, _, __,
{name} = movies [favoriteMovieID] || {name: 'Unknown Movie'},
{name: person} = users [userID] || {name: 'Unknown Person'}
) => ({
...a,
[name]: [... (a [name] || []), person]
}), {})
const profiles = [{id: 1, userID: "1", favoriteMovieID: "1"}, {id: 2, userID: "2", favoriteMovieID: "1"}, {id: 3, userID: "4", favoriteMovieID: "5"}, {id: 4, userID: "6", favoriteMovieID: "5"}, {id: 5, userID: "5", favoriteMovieID: "7"}]
const users = {1: {id: 1, name: "Jane Cruz", userName: "coder"}, 2: {id: 2, name: "Matthew Johnson", userName: "mpage"}, 4: {id: 4, name: "Nicholas Lain", userName: "nlain"}, 5: {id: 5, name: "Fred Flintstone", userName: "bedrock1"}}
const movies = {1: {id: 1, name: 'Planet Earth 1'}, 2: {id: 2, name: 'Selma'}, 5: {id: 5, name: 'Forrest Gump'}}
console .log (
groupNamesByMovie (profiles, users, movies)
)
Обратите внимание, что аргументы _
и __
предназначены только для использования в качестве заполнителей, поскольку нас не волнуют reduce
index
и array
параметры.
Обновление
Поступил запрос на уточнение. Для сравнения, вот более императивная версия той же идеи:
const getNamesByMovie = (profiles, users, movies) =>
profiles .reduce ((acc, {userID, favoriteMovieID}) => {
const movie = movies [favoriteMovieID]
const name = movie ? movie.name : 'Unknown Movie'
const user = users [userID]
const person = user ? user.name : 'Unknown Person'
const fans = acc [name] || []
return {
... acc,
[name]: [... fans, person]
}
}, {})
И если вы хотите избежать этой потенциальной проблемы с производительностью, вы можете заменить оператор return
чем-то вроде этого:
acc [name] = fans
fans .push (person)
return acc
Любой из них делает то же самое, что и оригинал выше. Я выбираю этот начальный стиль, потому что мне не нравится изменять объект-аккумулятор, я предпочитаю всегда создавать новую версию ... и потому что я предпочитаю работать с выражениями, а не с операторами. Но к этому стилю нужно привыкнуть.
Вы также спросили, как мы передали дополнительные параметры в обратный вызов reduce
. Мы этого не делаем. Вместо этого мы определяем некоторые дополнительные параметры и инициализируем их на основе более ранних параметров.