#javascript #json #ecmascript-6 #lodash #transformation
#javascript #json #ecmascript-6 #Lodash #преобразование
Вопрос:
Представьте, что у меня есть следующий массив JSON:
[
{
"team": "Colts",
"players": [
{
"name": "Andrew Luck",
"position": "quarterback"
},
{
"name": "Quenton Nelson",
"position": "guard"
}
]
},
{
"team": "Patriots",
"players": [
{
"name": "Tom Brady",
"position": "quarterback"
},
{
"name": "Shaq Mason",
"position": "guard"
}
]
}
]
И я хочу преобразовать и выровнять JSON следующим образом:
[
{
"name": "Andrew Luck",
"position": "quarterback",
"team": "Colts"
},
{
"name": "Quenton Nelson",
"position": "guard",
"team": "Colts"
},
{
"name": "Tom Brady",
"position": "quarterback",
"team": "Patriots"
},
{
"name": "Shaq Mason",
"position": "guard",
"team": "Patriots"
}
]
Как бы я сделал это с помощью синтаксиса ES6 или Lodash?
Ответ №1:
С помощью простых циклов (ES2015):
const players = [];
for (const team of teams) {
for (const player of team.players) {
players.push(Object.assign({team: team.team}, player));
}
}
Вы можете использовать object spread вместо Object.assign
, если ваша среда поддерживает это.
С Array#flatMap
(официально будет частью ES2019 или использовать Lodash):
const players = teams.flatMap(
team => team.players.map(player => {...player, team: team.team})
);
Ответ №2:
Используйте Array#reduce
метод вместе с Array#map
методом.
let res = data.reduce((arr, { team, players }) => arr.concat(players.map( obj => ({...obj, team }))), []);
// or
let res = data.reduce((arr, { team, players }) => [...arr, ...players.map( obj => ({...obj, team }))], []);
// or
let res = data.reduce((arr, { team, players }) => (arr.push(...players.map( obj => ({...obj, team }))),arr), []);
var data = [{
"team": "Colts",
"players": [{
"name": "Andrew Luck",
"position": "quarterback"
},
{
"name": "Quenton Nelson",
"position": "guard"
}
]
},
{
"team": "Patriots",
"players": [{
"name": "Tom Brady",
"position": "quarterback"
},
{
"name": "Shaq Mason",
"position": "guard"
}
]
}
]
let res = data.reduce((arr, {
team,
players
}) => arr.concat(players.map(obj => ({ ...obj,
team
}))), []);
// or
let res1 = data.reduce((arr, {
team,
players
}) => [...arr, ...players.map(obj => ({ ...obj,
team
}))], []);
// or
let res2 = data.reduce((arr, {
team,
players
}) => (arr.push(...players.map(obj => ({ ...obj,
team
}))), arr), []);
console.log(res, res1, res2)
Ответ №3:
Вы можете использовать lodah _.flatMap()
для итерации массива и выравнивания результата. Внутреннее использование _.map()
для перебора игроков и добавления team
с использованием объекта spread:
const arr = [{"team":"Colts","players":[{"name":"Andrew Luck","position":"quarterback"},{"name":"Quenton Nelson","position":"guard"}]},{"team":"Patriots","players":[{"name":"Tom Brady","position":"quarterback"},{"name":"Shaq Mason","position":"guard"}]}]
const result = _.flatMap(arr, ({ team, players }) =>
_.map(players, o => ({ team, ...o }))
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Вы можете сделать то же самое с Array.flatMap()
и Array.map()
:
const arr = [{"team":"Colts","players":[{"name":"Andrew Luck","position":"quarterback"},{"name":"Quenton Nelson","position":"guard"}]},{"team":"Patriots","players":[{"name":"Tom Brady","position":"quarterback"},{"name":"Shaq Mason","position":"guard"}]}]
const result = arr.flatMap(({ team, players }) =>
players.map(o => ({ team, ...o }))
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Ответ №4:
const data = [
{
"team": "Colts",
"players": [
{
"name": "Andrew Luck",
"position": "quarterback"
},
{
"name": "Quenton Nelson",
"position": "guard"
}
]
},
{
"team": "Patriots",
"players": [
{
"name": "Tom Brady",
"position": "quarterback"
},
{
"name": "Shaq Mason",
"position": "guard"
}
]
}
]
const flatData = data.map(d => {
const { team } = d
const assignedPlayers = d.players.map(player => ({ team, ...player }))
return assignedPlayers
}).flat()
console.log(flatData)
Ответ №5:
С помощью ES6 (оператор распространения) наряду с reduce
и concat
:
const arr = [{
"team": "Colts",
"players": [{
"name": "Andrew Luck",
"position": "quarterback"
},
{
"name": "Quenton Nelson",
"position": "guard"
}
]
},
{
"team": "Patriots",
"players": [{
"name": "Tom Brady",
"position": "quarterback"
},
{
"name": "Shaq Mason",
"position": "guard"
}
]
}
]
console.log(arr.reduce((acc, obj) => {
return acc.concat(...obj.players.map(player => {
return Object.assign({
team: obj.team
}, player)
}))
}, []));
Комментарии:
1. Для пояснения будущим посетителям:
reduce
существовал до ES6.
Ответ №6:
Это можно сделать просто с помощью следующего кода! Проверьте это!
var inputArray = [{"team":"Colts","players":[{"name":"Andrew Luck","position":"quarterback"},{"name":"Quenton Nelson","position":"guard"}]},{"team":"Patriots","players":[{"name":"Tom Brady","position":"quarterback"},{"name":"Shaq Mason","position":"guard"}]}]
var result = [];
inputArray.forEach(function(elem) {
const players = elem.players;
players.forEach(function(child) {
const obj = {};
obj["name"] = child.name;
obj["position"] = child.position;
obj["team"] = elem.team;
result.push(obj);
});
});
console.log(result);
.as-console-wrapper{max-height: 100% !important; top:0px;}
Ответ №7:
Вот еще одна альтернатива с комбинацией Array.reduce()
и Array.forEach()
:
let input = [
{
"team": "Colts",
"players": [
{
"name": "Andrew Luck",
"position": "quarterback"
},
{
"name": "Quenton Nelson",
"position": "guard"
}
]
},
{
"team": "Patriots",
"players": [
{
"name": "Tom Brady",
"position": "quarterback"
},
{
"name": "Shaq Mason",
"position": "guard"
}
]
}
];
let output = input.reduce((acc, {team, players}) =>
{
players.forEach(({name, position}) => acc.push({name, position, team}));
return acc;
}, []);
console.log(output);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}