J'ai un objet JSON comme celui-ci:
let groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
let groubedByExchange=groupBy(JSON_data, 'group');
Je veux convertir ce JSON au format ci-dessous par JS:
[{
"name":"animal",
"children":[
{"name":"cat", "value":17},
{"name":"dog", "value":6},
{"name":"snak", "value":2}
]},
{
"name":"car",
"children":[
{"name":"bmw", "value":11},
{"name":"tesla", "value":23}
]}]
J'essaye pour convertir et filtrer par la fonction Réduire mais je n'ai pas pu convertir dans ce format.
EDIT:
Le code que j'ai testé était celui-ci. p >
[{
"name" : "cat",
"value" : 17,
"group" : "animal",
},
{
"name" : "dog",
"value" : 6,
"group" : "animal",
},
{
"name" : "snak",
"value" : 2,
"group" : "animal",
},
{
"name" : "tesla",
"value" : 11,
"group" : "car",
},
{
"name" : "bmw",
"value" : 23,
"group" : "car",
}]
7 Réponses :
const arr = [{
"name": "cat",
"value": 17,
"group": "animal",
},
{
"name": "dog",
"value": 6,
"group": "animal",
},
{
"name": "snak",
"value": 2,
"group": "animal",
},
{
"name": "tesla",
"value": 11,
"group": "car",
},
{
"name": "bmw",
"value": 23,
"group": "car",
}
]
const newFormat = arr.reduce((pre, cur) => {
const group = pre.find(grp => grp.name === cur.group)
if (group) {
group.children.push({
name: cur.name,
value: cur.value
})
return pre
}
const newGroup = {
name: cur.group,
children: [{
name: cur.name,
value: cur.value
}]
}
pre.push(newGroup)
return pre
}, [])
console.log(newFormat)
voilà. vous essayez d'abord de trouver ce groupe dans un nouveau tableau, s'il existe, vous lui ajoutez cet enfant. sinon, vous créez le groupe et le tableau des enfants et le poussez vers le tableau
Vous pouvez créer un tableau et rechercher le même groupe dans le tableau.
.as-console-wrapper { max-height: 100% !important; top: 0; }
var array = [{ name: "cat", value: 17, group: "animal" }, { name: "dog", value: 6, group: "animal" }, { name: "snak", value: 2, group: "animal" }, { name: "tesla", value: 11, group: "car" }, { name: "bmw", value: 23, group: "car" }],
result = array.reduce((r, { group: name, ...object }) => {
var temp = r.find(o => o.name === name);
if (!temp) r.push(temp = { name, children: [] });
temp.children.push(object);
return r;
}, []);
console.log(result);
Ce serait ma solution ES6, utilisant la carte et la réduction:
const data = [
{
name: "cat",
value: 17,
group: "animal"
},
{
name: "dog",
value: 6,
group: "animal"
},
{
name: "snak",
value: 2,
group: "animal"
},
{
name: "tesla",
value: 11,
group: "car"
},
{
name: "bmw",
value: 23,
group: "car"
}
];
const grouped = data.reduce((acc, currItem) => {
const groupKey = currItem.group;
if (!acc[groupKey]) {
acc[groupKey] = [currItem];
} else {
acc[groupKey].push(currItem);
}
return acc;
}, {});
const res = Object.keys(grouped).map(key => ({
name: key,
children: grouped[key].map(groupItem => ({
name: groupItem.name,
value: groupItem.value
}))
}));
console.log(res);
Vérifiez la sortie de la console pour voir les résultats intermédiaires.
Je pense que certaines des autres réponses utilisent un find () inutile (qui est O (n)) alors que vous pouvez simplement tester si une clé de groupe actuelle est déjà là dans O (1).
Je stocke les résultats groupés dans une variable intermédiaire groupée pour plus de clarté, mais tout peut être inséré .
Utilisation de Array # from, Array # reduction, Array # concat, destructuring, spread syntax et Map.
const data=[{"name":"cat","value":17,"group":"animal",},{"name":"dog","value":6,"group":"animal",},{"name":"snak","value":2,"group":"animal",},{"name":"tesla","value":11,"group":"car",},{"name":"bmw","value":23,"group":"car",}];
const res = Array.from(
data.reduce((a,{group, ...rest})=>{
return a.set(group, [rest].concat(a.get(group)||[]));
}, new Map())
).map(([group, children])=>({group,children}));
console.log(res);
Et voilà. Vous pouvez utiliser lodash pour réaliser la même chose.
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
var data = [{
"name": "cat",
"value": 17,
"group": "animal",
},
{
"name": "dog",
"value": 6,
"group": "animal",
},
{
"name": "snak",
"value": 2,
"group": "animal",
},
{
"name": "tesla",
"value": 11,
"group": "car",
},
{
"name": "bmw",
"value": 23,
"group": "car",
}
]
var result = _(data)
.groupBy('group')
.map((group, name) =>
({
name,
children: _.map(group, ({
name: name,
value
}) => ({
name,
value
}))
}))
.value()
console.log(result)
Une solution simple consiste à créer un dictionnaire intermédiaire et à le transformer en votre structure de sortie.
Vous pouvez utiliser Array.reduce () , Object.entries () code> et Array.map () pour le faire:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const groupBy = prop => data => {
return data.reduce((dict, item) => {
const { [prop]: _, ...rest } = item;
dict[item[prop]] = [...(dict[item[prop]] || []), rest];
return dict;
}, {});
};
const result = Object.entries(groupBy('group')(data))
.map(([key, value]) => ({ name: key, children: value }));
console.log(result);
L'utilisation de l'opérateur de propagation la rend une ligne plus courte et toujours lisible:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) =>
Object.assign(acc, { [group]: [...(acc[group] || []), { name, value }] })
, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
Et une ligne plus courte avec l'opérateur virgule:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) =>
(acc[group] = [...(acc[group] || []), { name, value }], acc)
, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
La même chose peut être faite avec Object.assign():
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) => {
acc[group] = [...(acc[group] || []), { name, value }];
return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
Et enfin, un peu plus long mais avec une fonction groupBy réutilisable:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) => {
acc[group] = (acc[group] || []);
acc[group].push({ name, value });
return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
Bonne utilisation d'Object.entries. J'aime aussi le acc [group] = (acc [group] || []); pour éviter l'instruction if. Cela devrait être la réponse acceptée imo.
const transform = things =>
things.reduce((acc, { name, value, group }) => {
const existingGroup = acc.find(g => g.name === group) || {};
return [
...acc.filter(g => g.name !== group),
{
...existingGroup,
name: group,
children: [...(existingGroup.children || []), { name, value }],
},
];
}, []);
Copie possible de Tableau de groupe d'imbrication d'objets certaines des clés avec des noms spécifiques