I am trying to filter a sub array of a parent array and my results are coming back empty. I am trying to find matches to the color_family.
My array looks like:
const arr =[
{
"id": 123,
"acf": {
"product_colors": [
{
"color_family": "grey"
},
{
"color_family": "taupe"
}
]
}
},
{
"id": 456,
"acf": {
"product_colors": [
{
"color_family": "red"
},
{
"color_family": "taupe"
}
]
}
}
]
What I am filtering on is
const findColors = ["grey", "taupe"]
What I have tried with no luck is
const res = arr.filter(
x => x.acf.product_colors.find(
color_family => findColors.includes(color_family)
)
)
This is returning no results when it should return 2 results. Can someone point me in the right direction?
In addition to the typo, the param to the find argument is an object with color_family:
const res = arr.filter(x => x.acf.product_colors.find(col => {
return findColors.includes(col.color_family);
}))
Related
Say I have an array of objects as follows:
data = [
{
"id":34
},
{
"id":35
},
{
"id":36
},
{
"id":37
}
]
and another array as follows:
myNumberArray = [1,2,3,4]
They might be much larger, but the number of elements in both arrays will always be the same. I want to modify each element of data by adding a number attribute, assigning it the value from the corresponding element of myNumberArray.
When done, data will look as follows:
data = [
{
"number":1,
"id":34
},
{
"number":2,
"id":35
},
{
"number":3,
"id":36
},
{
"number":4,
"id":37
}
]
How can I do this?
myNumberArray = [1,2,3,4]
data = [
{
"id":34
},
{
"id":35
},
{
"id":36
},
{
"id":37
}
]
data.forEach((elem, index)=>{
data[index]["number"]=myNumberArray[index];
})
console.log(data);
This should solve your problem.
Explanation:
I used forEach to iterate over the data array, forEach accepts two parameters, the current value at an index, and the value.
Since, yours is a one-to-one mapping, we are using the current index to access the value at the same index in myNumberArray and assigning that new value in data for number key.
Try the following solution:
let myNumberArray = [1,2,3,4];
let data = [
{
"id":34
},
{
"id":35
},
{
"id":36
},
{
"id":37
}
];
const updatedArray = data.map((item,index)=> {
return {
...item,
"number":myNumberArray[index]
}
});
console.log(updatedArray);
let myNumberArray = [1,2,3,4]
let data = [
{
"id":34
},
{
"id":35
},
{
"id":36
},
{
"id":37
}
]
data = data.map( (x, i) => ({ number: myNumberArray[i], id: x.id}) )
console.log(data)
for (let i in myNumberArray) {
Object.assign(data[i], {
number: myNumberArray[i]
})
}
I wanted to filter out the data. I wanted to check if data on data1 is found on data2 and to check if it has errorMessages. Please check my code below. Is there a better way to do it?
data1
[
{
"ids": "0111",
},
{
"ids": "0222",
},
{
"ids": "0333",
}
]
data2
[
{
"id": "0111",
"errorMessages": [
{
"message": ["sample error message 1"]
}
]
},
{
"id": "0333",
"errorMessages": []
}
]
Code
const output= data1.filter(
(element) => element.ids === data2.find((data) => data).id
);
console.log("output", output);
.find((data) => data) doesn't do anything useful - each item in the array is an object, which is truthy, so that'll always return the first element in the array.
If you did want to .find a matching element in the other array - then a better approach would be to make a Set of the IDs found in the other array first (Set lookup is much quicker - O(1) - than .find, which is O(n)).
You also need to implement the logic to check if the errorMessages is empty.
const data1 = [
{
"ids": "0111",
},
{
"ids": "0222",
},
{
"ids": "0333",
}
]
const data2 = [
{
"id": "0111",
"errorMessages": [
{
"message": ["sample error message 1"]
}
]
},
{
"id": "0333",
"errorMessages": []
}
]
const ids = new Set(
data2
.filter(item => item?.errorMessages.length)
.map(item => item.id)
);
const output= data1.filter(
element => ids.has(element.ids)
);
console.log("output", output);
Without Set, but use Object as the map.
const IDKeys = {};
data2.forEach(data => {
if (data.errorMessages.length){
IDKeys[data.id] = true; // means valid
}
})
const filteredArray = data1.filter(data => IDKeys[data.id]);
This would be only O(n) since accessing key on object is O(1)
I am having difficulties formatting some data. Currently, I receive data in the following structure.
[
{
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
}
]
I essentially need to modify this or even create a new object, that takes the following structure.
[
{
id: 1, //q1
answers: [
{
answer: '5',
},
],
},
{
id: 2, //q2
answers: [
{
answer: '13',
},
{
answer: '12',
},
],
},
{
id: 3, //q3
answers: [
{
answer: 'test',
},
],
},
];
So the id in the above would be obtained by remove the q and getting the number in the first data object. It would then have an answers array that would have an object for each answer.
I have been attempting this but have gotten lost. I don't know if I should use loops, mapping, filters etc. To be honest, the furthest I have got so far is obtaining the keys
var modified = data.map(function(item) {
return Object.keys(item)
})
I have created a JSFiddle where I have been attempting to do this.
Is there any way I can achieve the data I am after?
Many thanks
Please use map function.
const data = {
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
};
const result = Object.keys(data).map(key => {
let item = {id: key.substring(1), answers: []};
if(typeof data[key] === "string")
item.answers.push({answer: data[key]});
else
item.answers = data[key].map(val => ({answer: val}));
return item;
});
console.log(result)
const inputData = [
{
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
}
]
function answerMapper(objVal, id){
return Array.isArray(objVal)
?
{ id, answers: objVal.map(answer => ({ answer }))}
:
{ id, answers: [{answer: objVal }] }
}
function formatObject(obj){
return Object.keys(obj).map((k, i) => answerMapper(obj[k], i+1));
}
const result = inputData.map(obj => formatObject(obj));
// remove flatMap if your inputData has more than one entry
console.log(result.flatMap(x => x));
map over the first element of the data with Object.entries, grab the key and value, create a new answers array and return a new object.
const data = [{
"q1": "5",
"q2": [
"13",
"12",
],
"q3": "test",
}];
const out = Object.entries(data[0]).map(obj => {
const [ key, value ] = obj;
const id = Number(key[1]);
// If the the value is an array
// return a new array of mapped data
// Otherwise return an array containing
// one object
const answers = Array.isArray(value)
? value.map(el => ({ answer: el }))
: [{ answer: value }];
// Return the new object
return { id, answers };
});
console.log(out);
lets create a pure function which accepts the object in the array like so
const processObject = obj => Object.keys(obj).map(id => {
const answer = obj[id];
const answers = Array.isArray(answer) ? answer : [answer]
const answerObjectArray = answers.map(ans => ({
answer: ans
}));
return {
id: +id.substring(1),
answers: answerObjectArray
}
});
const dataArray = [{
"q1": "5",
"q2": [
"13",
"12",
],
"q3": "test",
}];
const output = processObject(dataArray[0]);
console.log(output);
i have an array A
const arrayA = [
{
id:a,
check:false
},
{
id:b,
check:false
},
{
id:c,
check:false
}
and an array B
const arrayB = [
{
id:a,
},
{
id:b,
}
]
and i want to check if arrayB is exist arrayA by id, then change check to true. Using lodash or js array methods
Hopefully I understood your question correctly but this is the solution I came up with.
arrayA.map((item) => ({ ...item, check: arrayB.some(({ id: idB }) => item.id === idB ) }))
You can use nested forEach loops, and check, if id matches then set check to true.
const arrayA = [{
id: "a",
check: false
},
{
id: "b",
check: false
},
{
id: "c",
check: false
}
]
const arrayB = [{
id: "a",
},
{
id: "b",
}
]
arrayB.forEach((b)=>{
arrayA.forEach((a)=>{
if(b.id == a.id){
a.check = true;
}
})
})
console.log(arrayA);
You could create an array containing the ids of arrayB and then check the objects in arrayA like
const arrayA = [
{
id: 'a',
check:false
},
{
id:'b',
check:false
},
{
id:'c',
check:false
} ];
const arrayB = [
{
id:'a',
},
{
id:'b',
}
];
const idsB = arrayB.map( obj => obj.id);
arrayA.forEach(obj => { if(idsB.indexOf(obj.id) > -1) obj.checked = true; } );
arrayA.forEach(obj => {console.log(JSON.stringify(obj))});
I could come up with this, which is not different than double loop, but may read easier.
arrayA.map((a) => {
a.check = arrayB.findIndex((b) => b.id === a.id) != -1;
return a;
});
Try this code it may help you
const arrayA = [
{id:'a',check:false},
{id:'b',check:false},
{id:'c',check:false}
]
const arrayB = [
{id:'a',},
{id:'b',}
]
arrayB.map(i => {
return i.check = arrayA.find(item => i.id == item.id)?.check;
});
console.log(arrayB)
I want to make the following newArray using by following testArray.
newArray↓
let newArray = [
{section:"business",name:["Bob","John"]},
{section:"H&R",name:["Jen","Bobby"]},
]
testArray↓
let test = [
{section:"business",name:"Bob"},
{section:"business",name:"John"},
{section:"H&R",name:"Jen"},
{section:"H&R",name:"Bobby"},
]
First of all, I tried to find some key elements using by filter method like below.
let newArray = test.filter((x:any,i,self)=>
self.indexOf(x.section)===i
)
but this code output is [].
So, how do I make code to get my expected output?
Does anyone help me?
Use Array.reduce():
let test=[{section:"business",name:"Bob"},{section:"business",name:"John"},{section:"H&R",name:"Jen"},{section:"H&R",name:"Bobby"}];
let newArray = test.reduce((acc,cur) => {
if(acc.some(el => el.section === cur.section)){
acc.forEach((el,idx) => {
if(el.section === cur.section){
acc[idx].name.push(cur.name)
}
})
}else{
cur.name = [cur.name]
acc.push(cur)
}
return acc
},[])
console.log(newArray)
you can try this
const test = [{
section: "business",
name: "Bob"
},
{
section: "business",
name: "John"
},
{
section: "H&R",
name: "Jen"
},
{
section: "H&R",
name: "Bobby"
},
];
// gather sections
const sections = {};
test.forEach(t => {
sections[t.section] = sections[t.section] || [];
sections[t.section].push(t.name);
});
// convert sessions to array
const newArray = Object.keys(sections).map(k => {
return {
section: k,
name: sections[k]
};
});
console.log(newArray);