I want to write a function that transfers this object
[
{
"id": "656DDXFT565xX",
"name": "Black item",
"categorues": [
"Black",
"White"
],
"price": 5
}
]
to be like a thing like that
[
{
"Black": [
{
"id": "656DDXFT565xX",
"name": "Black item",
"categories": [
"Black",
"White"
],
"price": 5
}
]
},
{
"White": [
{
"id": "656DDXFT565xX",
"name": "Black item",
"categories": [
"Black",
"White"
],
"price": 5
}
]
}
]
I tried with Array.reduce, but I don't know how to render this.
If anyone has any hindsight on this
You can iterate over the categorues of each item using .map to get the expected result. This a solution using lodash:
const data = [
{ "id":"656DDXFT565xX", "name":"Colored item", "categorues":["Black","White"], "price":5 },
{ "id":"656DDXFT565x2", "name":"White item", "categorues":["White"], "price":5 },
{ "id":"656DDXFT565x3", "name":"Black item", "categorues":["Black"], "price":5 }
];
const _reduceElem = (elem={}) => {
const { categorues=[] } = elem;
return _.map( categorues, cat => ({ [cat]: [_.cloneDeep(elem)] }) );
}
const res = _.reduce(data, (acc,item) => {
acc = [...acc, ..._reduceElem(item)];
return acc;
}, []);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
let before = [
{
"id": "656DDXFT565xX-BW",
"name": "Black and white item",
"categories": [
"Black",
"White"
],
"price": 5
},
{
"id": "656DDXFT565xX-K",
"name": "Black item",
"categories": [
"Black"
],
"price": 10
},
{
"id": "656DDXFT565xX-W",
"name": "White item",
"categories": [
"White"
],
"price": 15
}
]
let after = before.reduce(
(acc, val) => {
val.categories.forEach(cat => {
acc[cat] ||= []
// if this fails, use newer version of node, or use
// if(!acc.cat) acc.cat = []
acc[cat].push(val)
})
return acc
},
{}
)
console.log(after)
Since you just want to extract categorues as a key. You don't need to use reduce, just using map to loop the categorues is fine.
const origin = [
{
"id": "656DDXFT565xX",
"name": "Black item",
"categorues": [
"Black",
"White"
],
"price": 5
}
]
const categorues = origin[0].categorues;
const result = categorues.map(item => {
return {
[item]: origin
}
})
console.log(result)
Related
I have a nested array like below. There are about 100 de objects in the array. The de objects also have deg[0] array but most likely I will only have the first index. Now the trick is that the de are subset of deg. Which means each deg can have say 10 de. How can I retrieve the deg and there associated de and map it into a new array like:
newArray = [
deg1: [
{de1},
{de2}
],
deg2: [
{de1},
{de2}
]
]
Here is my nested array. I posted four but the list is over a 100.
{
"name": "Report",
"id": "2YYUEZ6I1r9",
"dse1": [
{
"de1": {
"name": "Number",
"id": "HjMOngg3kuy",
"de1-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "TB",
"id": "2XJB1JO9qX8"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2-av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg1": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de1": {
"name": "Number of",
"id": "a3dtGETTawy",
"de1av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Secondary",
"id": "w99RWzXHgtw"
}
]
}
},
{
"de2": {
"name": "Number of",
"id": "a3dtGETTawy",
"de2av": [
{
"value": "FHaQMPv9zc7",
"attribute": {
"id": "uwVkIP7PZDt"
}
},
{
"value": "something",
"attribute": {
"id": "FHaQMPv9zc7"
}
}
],
"deg2": [
{
"name": "Tertiary",
"id": "w99RWzXHgtw"
}
]
}
}
]
}
Group array of objects by property (this time a property to be matched by a reg exp) using Array.reduce.
Update: Ignoring missing keys.
var input={name:"Report",id:"2YYUEZ6I1r9",dse1:[{de1:{name:"Number",id:"HjMOngg3kuy","de1-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"TB",id:"2XJB1JO9qX8"}]}},{de2:{name:"Number of",id:"a3dtGETTawy","de2-av":[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg1:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de1:{name:"Number of",id:"a3dtGETTawy",de1av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Secondary",id:"w99RWzXHgtw"}]}},{de2:{name:"Number of",id:"a3dtGETTawy",de2av:[{value:"FHaQMPv9zc7",attribute:{id:"uwVkIP7PZDt"}},{value:"something",attribute:{id:"FHaQMPv9zc7"}}],deg2:[{name:"Tertiary",id:"w99RWzXHgtw"}]}}]}
var reg = new RegExp("^de[0-9]+$");
var reg2 = new RegExp("^deg[0-9]+$");
let obj = input['dse1'].reduce(function(agg, item) {
// do your group by logic below this line
var key = Object.keys(item).find(function(key) {
return key.match(reg) ? key : null;
})
if (key) {
var key2 = Object.keys(item[key]).find(function(key) {
return key.match(reg2) ? key : null;
})
agg[key] = agg[key] || [];
if (key2) {
var to_push = {}
to_push[key2] = item[key][key2]
agg[key].push(to_push)
}
}
// do your group by logic above this line
return agg
}, {});
console.log(obj)
.as-console-wrapper {
max-height: 100% !important;
}
I have this JSON data:
{
"data": [
{
"category": {
"documentId": "c8kr0cv012vtr8vm3iug",
"title": "Art"
},
"subcategories": [
{
"documentId": "c8kr7nv012vtr8vm3l8g",
"title": "Architecture"
},
{
"documentId": "c8kr7nv012vtr8vm3lag",
"title": "Dance"
},
{
"documentId": "c8kr7nv012vtr8vm3lbg",
"title": "Fashion"
}
]
},
{
"category": {
"documentId": "c8kr0cv012vtr8vm3iqg",
"title": "Business"
},
"subcategories": [
{
"documentId": "c8kr3d7012vtr8vm3jjg",
"title": "Crypto"
},
{
"documentId": "c8kr3d7012vtr8vm3jj0",
"title": "Finance"
},
{
"documentId": "c8kr3d7012vtr8vm3jkg",
"title": "Marketing"
}
]
}
]
}
I have tagview in my mobile screen so user can select multiple subcategory at a same time by select deselect so if i choose 2 subcategory from Art and 2 from Business then expected post payload should be like below
{
"data": [
{
"category": "c8kr0cv012vtr8vm3iug",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag"
]
},
{
"category": "c8kr0cv012vtr8vm3iqg",
"subcategories": [
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
}
]
}
So my code is like below
const tempDefaultPayload = dataPayload.map(x => {
if (x.category) {
x.subcategories?.push(subcategory);
if (userData?.userInterests?.map(v => v.category.documentId === category)) {
const arrayNewData: any = [];
const newData: any = userData?.userInterests?.map(i =>
i.subcategories?.map(k => {
arrayNewData.push(k?.documentId);
return k?.documentId;
}),
);
x.subcategories?.push(...arrayNewData);
}
return x;
}
return x;
})
When I run above code payload is not passing correct
[
{
"category": "c8kr0cv012vtr8vm3iug",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag",
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
},
{
"category": "c8kr0cv012vtr8vm3iqg",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag",
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
}
]
It is passing all selected subcategory in both array any idea how can I solve this ?
If you have the selected tag ids in the array selectedTags and your json as a variable called data:
const tempDefaultPayload = {
data: data.data.map(x => {
"category": x.category.documentId,
"subcategories": x.subcategories.map(subcat =>
subcat.documentId).filter(item => selectedTags.includes(item))
})
}
Playground example
Am looking to map through an array, take the key/value of a specified field, then merge it into the main object.
Currently my array looks like:
const data = [
{
"id": "3QXNO4SDo08FgAfQy3z5",
"title": "Team One",
"scores": [
{
"id": "DbkZljn22YSGVBLxiT4o",
"score": 88
},
{
"id": "v7ss2ypT4qf9RIvIynJp"
"score": 5,
}
]
},
{
"id": "EmoL3dlPWpOPPiLixIYJ",
"title": "Team Two",
"scores": [
{
"id": "DbkZljn22YSGVBLxiT4o",
"score": 77,
},
{
"id": "v7ss2ypT4qf9RIvIynJp",
"score": 0,
}
]
}
]
And I need to simplify it down to:
[
{
"id": "3QXNO4SDo08FgAfQy3z5",
"title": "Team One",
"DbkZljn22YSGVBLxiT4o": 88,
"v7ss2ypT4qf9RIvIynJp": 5,
},
{
"id": "EmoL3dlPWpOPPiLixIYJ",
"title": "Team Two",
"DbkZljn22YSGVBLxiT4o": 77,
"v7ss2ypT4qf9RIvIynJp": 0,
}
]
Taking the unique ID of the score and using it as my object key.
I imagine this requires nested looping to get the result. I would post my coding attempts, but they were seriously flawed and confusing.
You can combine Array#map and Array#reduce to achieve the desired output.
const mapped = data.map(({ scores, ...rest }) => ({
...rest,
...scores.reduce((output, score) => ({ ...output, [score.id]: score.score }), {})
}));
your questiopn is not clear ..
but this answer may help you
const data= [
{
"id": "3QXNO4SDo08FgAfQy3z5",
"title": "Team One",
"scores": [
{
"id": "DbkZljn22YSGVBLxiT4o",
"score": 88
},
{
"id": "v7ss2ypT4qf9RIvIynJp"
"score": 5,
}
]
},
{
"id": "EmoL3dlPWpOPPiLixIYJ",
"title": "Team Two",
"scores": [
{
"id": "DbkZljn22YSGVBLxiT4o",
"score": 77,
},
{
"id": "v7ss2ypT4qf9RIvIynJp",
"score": 0,
}
]
}
]
by click on data field:
const array = [];
function handleSelect(id) {
const copyData = [...data];
const foundItems = copyData.map(item => item.id === id);
array.push(foundItems)
}
finally array is:
const array = [
{
"id": "3QXNO4SDo08FgAfQy3z5",
"title": "Team One",
"DbkZljn22YSGVBLxiT4o": 88,
"v7ss2ypT4qf9RIvIynJp": 5,
},
{
"id": "EmoL3dlPWpOPPiLixIYJ",
"title": "Team Two",
"DbkZljn22YSGVBLxiT4o": 77,
"v7ss2ypT4qf9RIvIynJp": 0,
}
]
const flattenedArray = data.map((dt) => {
let ar = [];
dt.scores.forEach((n, i) => (ar = { ...ar, [n.id]: n.score }));
return { ...dt, ...ar };
});
Returns the desired flattened array.
This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 1 year ago.
can you help me with this problem with js\react?
I'm trying to manage 2 arrays due to obtain a new object based on their shared attribute (Array A: "id" and Array B: "parent")
I think isn't hard but I'm struggling to do it atm :(
Array A
[{
"id": "606f1a2bebb5fb53804dd3d5",
"name": "cc",
}, {
"id": "606f1a30cfe84430c41dce88",
"name": "bb",
}, {
"id": "606f1a4ed2ff554e4ea11b82",
"name": "ff",
}]
Array B
[{
"id": "3344",
"color": "pink",
"parent": "606f1a2bebb5fb53804dd3d5",
}, {
"id": "3453",
"color": "blue",
"parent": "606f1a30cfe84430c41dce88",
}, {
"id": "3331",
"color": "yellow",
"parent": "606f1a4ed2ff554e4ea11b82",
}, {
"id": "4442",
"color": "black",
"parent": "606f1a30cfe84430c41dce88",
}]
I want merge these two arrays and create a new one where the array B objects are split by "id" of array A.
Something like this:
[{
"606f1a2bebb5fb53804dd3d5": [{
"id": "3344",
"color": "pink",
"parent": "606f1a2bebb5fb53804dd3d5",
}]
}, {
"606f1a30cfe84430c41dce88": [{
"id": "3453",
"color": "blue",
"parent": "606f1a30cfe84430c41dce88",
}, {
"id": "4442",
"color": "black",
"parent": "606f1a30cfe84430c41dce88",
}]
}, {
"606f1a4ed2ff554e4ea11b82": [{
"id": "3331",
"color": "yellow",
"parent": "606f1a4ed2ff554e4ea11b82",
}]
}]
Thanks very much guys
You just need array b for grouping and another object for keeping track of the max key inside of a group.
const
data = [{ id: "3344", color: "pink", parent: "606f1a2bebb5fb53804dd3d5" }, { id: "3453", color: "blue", parent: "606f1a30cfe84430c41dce88" }, { id: "3331", color: "yellow", parent: "606f1a4ed2ff554e4ea11b82" }, { id: "4442", color: "black", parent: "606f1a30cfe84430c41dce88" }],
max = {},
result = data.reduce((r, o) => {
max[o.parent] = (max[o.parent] || 0) + 1;
(r[o.parent] ??= {})[max[o.parent]] = o;
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think you can loop through the items and then find the parent
let arrayC = [];
arrayB.forEach(item => {
let parent = array1.find(e => e.id === item.parent);
// do something here to combine it into one object
// then arrayC.push(newItem);
});
https://codesandbox.io/s/boring-snowflake-brksj?file=/src/index.js
const result = arrayA.reduce((acc, arrayAItem) => {
return {
...acc,
[arrayAItem.id]: arrayB.filter(
(arrayBItem) => arrayBItem.parent === arrayAItem.id
)
};
}, {});
}]
You can do this with map and filter functions of array.
const newArray = array1.map(array1Item => {
return { [array1Item.id]: array2.filter(array2Item => array2Item.parent === array1Item.id)}
})
Based on the two arrays that you have, I assume that they are only linked by their "parent" ids. If this is the case, you can reduce the B array using the A array as an accumulator.
const a = [
{ "id": "606f1a2bebb5fb53804dd3d5" , "name": "cc" },
{ "id": "606f1a30cfe84430c41dce88" , "name": "bb" },
{ "id": "606f1a4ed2ff554e4ea11b82" , "name": "ff" },
];
const b = [
{ "id": "3344" , "color": "pink" , "parent": "606f1a2bebb5fb53804dd3d5" },
{ "id": "3453" , "color": "blue" , "parent": "606f1a30cfe84430c41dce88" },
{ "id": "3331" , "color": "yellow" , "parent": "606f1a4ed2ff554e4ea11b82" },
{ "id": "4442" , "color": "black" , "parent": "606f1a30cfe84430c41dce88" },
];
const c = Object
.entries(b.reduce((acc, { id, color, parent }) =>
({ ...acc, [parent]: {
...acc[parent],
colors: [...acc[parent].colors, { id, color } ]
}}),
Object.fromEntries(a.map(({ id, name }) =>
[ id, { name, colors: [] } ]))))
.map(([ id, value ]) => value);
console.log(c);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Currently I have the below object structure,
`let selectedOptions = {
"color": {
"id": "2",
"values": [
{
"value": "red",
"label": "Red",
"id": 1
},
{
"value": "blue",
"label": "Blue",
"id": 2
}
]
},
"size": {
"id": "19",
"values": [
{
"value": "medium",
"label": "Medium",
"id": 2
}
]
},
"demo": {
"id": "19",
"values": [
{
"value": "neylon",
"label": "Neylon",
"id": 2
}
]
}
.
.
.
N
}; `
And want to create array of objects from the above object like as below,
[
{ color: "red", size: "medium", demo: "neylon" },
{ color: "blue", size: "medium", demo: "neylon" }
]
I have tried like below but it didn't worked
https://jsfiddle.net/6Lvb12e5/18/
let cArr = [];
for(key in selectedOptions) {
selectedOptions[key].values.forEach(function(val,i) {
cArr.push({ [key]: val.value })
})
}
Thanks
You could take the wanted parts, like color, size and demo and build a cartesian product out of the given data.
const
cartesian = (a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []),
options = { color: { id: "2", values: [{ value: "red", label: "Red", id: 1 }, { value: "blue", label: "Blue", id: 2 }] }, size: { id: "19", values: [{ value: "small", label: "Small", id: 1 }, { value: "medium", label: "Medium", id: 2 }] }, demo: { id: "19", values: [{ value: "neylon", label: "Neylon", id: 2 }] } },
parts = Object
.entries(options)
.map(([k, { values }]) => [k, values.map(({ value }) => value)]),
keys = parts.map(([key]) => key),
result = parts
.map(([, values]) => values)
.reduce(cartesian)
.map(a => Object.assign(...a.map((v, i) => ({ [keys[i]]: v }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am not sure that is this the best way to do this, and even the data is missing but as a comment, it is quite big to post but can try:
let selectedOptions = {
"color": {
"id": "2",
"values": [
{
"value": "red",
"label": "Red",
"id": 1
},
{
"value": "blue",
"label": "Blue",
"id": 2
}
]
},
"size": {
"id": "19",
"values": [
{
"value": "medium",
"label": "Medium",
"id": 2
}
]
},
"demo": {
"id": "19",
"values": [
{
"value": "neylon",
"label": "Neylon",
"id": 2
}
]
}
};
let cArr = [];
var obj = {};
var glob;
for(key in selectedOptions) {
selectedOptions[key].values.forEach(function(val,i) {
obj[key] = val.value;
}
)
glob = obj;
}
cArr.push(glob);
console.log(cArr)