I'm trying to use the reduce function in order to iterate through an array of objects and to get an output summing up the data shown inside of the array of objects (a kind of duplicate remover in fact).
On data such as :
mainData = [
{data : {name: "item1", color: "red", type: ["metal", "wood"]}, id: 1},
{data : {name: "item2", color: "green", type: ["wood"]}, id: 2},
{data : {name: "item3", color: "green", type: ["wood", "stone", "marble"]}, id: 3},
{data : {name: "item4", color: "red", type: ["stone"]}, id: 4}
]
when using the function :
const getValues = (data, key) => {
return data.reduce((acc, item) => {
if(acc.indexOf(item.data[key]) > -1) {
return [...acc]
} else {
return [...acc, item.data[key]]
}
}, [data[0].data[key]]) //initial value
}
It will fork fine if I call this getValues
function getValues(mainData, "color")
for the color
key,
giving the following output : ["red", "green"]
, which is expected.
But if i call the function with getValues(mainData, "type")
, this function will ignore most of the values from the array type value from the key type
.
I tried to solve it by using a for
loop limited by data["type"].length
just before the if...else
condition of the reduce function, like this :
const getValues = (data, key) => {
return data.reduce((acc, item) => {
for(let i = 0; i < item.data[key].length; i ) {
if(acc.indexOf(item.data[key][i]) > -1) {
return [...acc]
} else {
return [...acc, item.data[key][i]]
}
}
}, [data[0].data[key][0]])
}
But it does not work either.
Anyone has an idea of how to solve this ?
CodePudding user response:
you can use flatMap
for that
like this
const mainData = [
{data : {name: "item1", color: "red", type: ["metal", "wood"]}, id: 1},
{data : {name: "item2", color: "green", type: ["wood"]}, id: 2},
{data : {name: "item3", color: "green", type: ["wood", "stone", "marble"]}, id: 3},
{data : {name: "item4", color: "red", type: ["stone"]}, id: 4}
]
const getValue = (data, key) => [...new Set(data.flatMap(({data}) => Array.isArray(data[key])?data[key]: [data[key]]))]
console.log(getValue(mainData, 'name'))
console.log(getValue(mainData, 'type'))
CodePudding user response:
It maybe easier to use a Set to dedupe the values.
const mainData=[{data:{name:"item1",color:"red",type:["metal","wood"]},id:1},{data:{name:"item2",color:"green",type:["wood"]},id:2},{data:{name:"item3",color:"green",type:["wood","stone","marble"]},id:3},{data:{name:"item4",color:"red",type:["stone"]},id:4}];
// Pass in the data, and the prop you want to look at
function finder(arr, prop) {
// Create a new set
const set = new Set();
// Iterate over the array of objects
for (const obj of arr) {
const value = obj.data[prop];
// If `value` is an array add each value to the set
if (Array.isArray(value)) {
value.forEach(v => set.add(v));
} else {
// Otherwise just add the value
set.add(obj.data[prop]);
}
}
// Return an array from the set
return [...set];
}
console.log(finder(mainData, 'color'));
console.log(finder(mainData, 'type'));
console.log(finder(mainData, 'name'));
CodePudding user response:
.flatMap()
the first layer searching forkeyA
("data"). Eachdata:{...}
object is converted into an array of pairs:[["name","item1"],["color","red"],["type",["metal","wood"]],...];
Another
.flatMap()
iterates through the array of pairs and returns a value when it gets a match withkeyB
. Everything else is returned as an empty array that will result in nothing since.flatMap()
flattens it's returns.([k, v]) => k === keyB ? v :[])
Finally, the return of both
flatMap()
s are made into aSet()
then theSet
is returned as an array sans duplicates.return [...new Set(output)];
const mainData = [
{data : {name: "item1", color: "red", type: ["metal", "wood"]}, id: 1},
{data : {name: "item2", color: "green", type: ["wood"]}, id: 2},
{data : {name: "item3", color: "green", type: ["wood", "stone", "marble"]}, id: 3},
{data : {name: "item4", color: "red", type: ["stone"]}, id: 4}
];
function compact(objArray, keyA, keyB) {
const output = objArray.flatMap(
obj => Object.entries(obj[keyA]).flatMap(
([k, v]) => k === keyB ? v :[]
)
);
return [...new Set(output)];
}
console.log(compact(mainData, 'data', 'type'));
console.log(compact(mainData, 'data', 'color'));
console.log(compact(mainData, 'data', 'name'));