Related
I have a following array of maps
let input = [
{"name":"apple", "type":"fruit", "color": "red"},
{"name":"apple", "type":"fruit", "color": "green"},
{"name":"tomato", "type":"fruit", "color": "red", "taste":"sweet"},
{"name":"tomato", "type":"fruit", "color": "green", "taste":"sour"}
];
How do I check if there are two elements in this array - one containing red apples and green tomatoes?
I tried this:
console.log (
input.some(
(subMap) => subMap.name == "tomato" && subMap.color == "green")
&&
input.some(
(subMap) => subMap.name == "apple" && subMap.color == "red"));
For the above array, this returns true.
Looking for a more concise way of checking this.
Something like
input =[
{"name":"apple", "type":"fruit", "color": "red"},
{"name":"apple", "type":"fruit", "color": "green"},
{"name":"tomato", "type":"fruit", "color": "red", "taste":"sweet"},
{"name":"tomato", "type":"fruit", "color": "green", "taste":"sour"}
];
subArray = [{"name" : "apple", "color":"red"} , {"name":"tomato", "color" : "green"}]
//This function should return true
(input.hasElementsMatching(subArray)) => true
Thanks in advance
So, for each object in the subArray you need to find an item in the input which contains all the keys/values of that
object
function arrayContainsObjects(array, check) {
return check.every((objectToCheck) => {
return array.some((item) => {
return Object.entries(objectToCheck).every(
([key, value]) => item[key] === value
);
});
});
}
const input = [{
"name": "apple",
"type": "fruit",
"color": "red"
},
{
"name": "apple",
"type": "fruit",
"color": "green"
},
{
"name": "tomato",
"type": "fruit",
"color": "red",
"taste": "sweet"
},
{
"name": "tomato",
"type": "fruit",
"color": "green",
"taste": "sour"
}
];
const subArray = [{
"name": "apple",
"color": "red"
}, {
"name": "tomato",
"color": "green"
}];
console.log( arrayContainsObjects(input,subArray) );
I 'm trying to find if array1 is is inside the nested array2.data.
const array1 = [
{
name: "Color",
value: "Yellow",
},
{
name: "Size",
value: "Small",
},
];
const array2 = [
{
"id": 1,
"data": [
{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Small"
}
]
},
{
"id": 2,
"data": [
{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Medium"
}
]
},
{
"id": 3,
"data": [
{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Large"
}
]
},]
this is what I have tread but not giving me the result I need :
array2.map(( a ) => {
a.data.map(( data ) => {
array1.map((option) => {
if( data === option) {
return data;
}
});
});
});
JSON.stringify() the needle array (array1) and the data attribute of each array member in array2 and compare the two; if they match, array1 is present in array2:
const array1 = [{
name: "Color",
value: "Yellow",
},
{
name: "Size",
value: "Small",
},
];
const array2 = [{
"id": 1,
"data": [{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Small"
}
]
},
{
"id": 2,
"data": [{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Medium"
}
]
},
{
"id": 3,
"data": [{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Large"
}
]
},
];
const dataArrayIsPresentInArray2 = needle => !!array2.find(cv => JSON.stringify(cv.data) === JSON.stringify(needle));
console.log(dataArrayIsPresentInArray2(array1)); // true
As mentioned in the comments, this method will only work for data structures serializable with JSON.stringify().
If the order of the objects in array1 does not matter, you can iterate through every item and use Array.every to check whether each item in the data property after stringification is equal to an item in array1 after stringification.
const array1=[{name:"Color",value:"Yellow"},{name:"Size",value:"Small"}],array2=[{id:1,data:[{name:"Color",value:"Yellow"},{name:"Size",value:"Small"}]},{id:2,data:[{name:"Color",value:"Yellow"},{name:"Size",value:"Medium"}]},{id:3,data:[{name:"Color",value:"Yellow"},{name:"Size",value:"Large"}]}];
const contains = array2.some(e => e.data.every(f => array1.some(g => JSON.stringify(g) == JSON.stringify(f))));
console.log(contains)
if you wanna just to check if arr1 in arr2.date
i would probably just
loop over arr2.data and compare each iteration to arr1 and if it is the same return or change some value to know the output .
something like :
// var that represent if arr1 inside arr2.data
let arr1InsideArr2= false
for (let i of array2){
if (i.data == array1){
return arr1InsideArr2= true
}
}
and then do with the var arr1InsideArr2 whatever you want to check .
This may be extremely simple but I've not been able to figure out how to iterate over and access the properties in the following mix (I think) of arrays and nested objects:
myFilters = {
"color_Filter": [{
"name": "BLUE",
"count": 1,
"dataId": "BLUE"
},
{
"name": "Black",
"count": 5,
"dataId": "Black"
},
{
"name": "Blue",
"count": 14,
"dataId": "Blue"
}
],
"size_Filter": [{
"name": "10",
"count": 16,
"dataId": "10"
},
{
"name": "12",
"count": 16,
"dataId": "12"
}
]
}
What would the correct looping structure be here to pull out name, count etc from the above? The desired output is to output a string from the above with color_Filter=BLUE,Black,Blue/size_Filter=10,12
I've tried a few different approaches and none of them have been successful so far.
You could map the entries of the object and create a string for each key. Get the name from the value array using map. Then join the array of strings with a /
const myFilters = {color_Filter:[{name:"BLUE",count:1,dataId:"BLUE"},{name:"Black",count:5,dataId:"Black"},{name:"Blue",count:14,dataId:"Blue"}],size_Filter:[{name:"10",count:16,dataId:"10"},{name:"12",count:16,dataId:"12"}]};
const output = Object.entries(myFilters)
.map(([k,arr]) => `${k}=${arr.map(a => a.name)}`)
.join("/")
console.log(output)
I have an object like this
let obj = {
"apple": {
"color": "red",
},
"banana": {
"color": "yellow"
}
}
I am getting an array of objects of this form
let arr = [
{
"count": "9904",
"fruit": "apple",
"type": "typea"
},
{
"count": "7142",
"fruit": "banana",
"type": "typeb"
},
{
"count": "4121",
"fruit": "apple",
"type": "typec"
}
]
I want to combine these two so that each item in objcan have variable no of properties so that final output look something like this
{
"apple": {
"color": "red",
"typea": "9904",
"typec": "4121"
},
"banana": {
"color": "yellow",
"typeb": "7142"
}
}
I tried running the array through a for loop but when I try to use the dynamic values in keys it shows error
for (let item of arr){
obj[item.fruit] = {...obj[item.fruit], item.type: item.count}
}
If instead of item.type I put some static value like "count" it works but I can't figure out how to use dynamic value
Can anyone suggest me what is the best way to accomplish this?
You should use computed property names with square brackets.
let obj = {
"apple": {
"color": "red",
},
"banana": {
"color": "yellow"
}
}
let arr = [
{
"count": "9904",
"fruit": "apple",
"type": "typea"
},
{
"count": "7142",
"fruit": "banana",
"type": "typeb"
},
{
"count": "4121",
"fruit": "apple",
"type": "typec"
}
]
for (let item of arr){
obj[item.fruit] = {...obj[item.fruit], [item.type]: item.count}
}
console.log(obj);
Here's a verbose and explicit example of how you can do this using Array.prototype.reduce.
(Note that MDN will be down for maintenance for up to an hour at some point today.)
const
obj = { apple:{color:"red"}, banana:{color:"yellow"} },
arr = [
{ fruit: "apple", type: "typeA", count: 9 },
{ fruit: "banana", type: "typeB", count: 7 },
{ fruit: "apple", type: "typeC", count: 4 }
];
arr.reduce( (theObj, current) => {
// Reduce loops through the array, updating theObj for each item
const
fruitName = current.fruit, // Gets fruit name
fruitObjInObj = theObj[fruitName], // Gets fruit obj
type = current.type, // Gets type from current item
count = current.count; // Gets count from current item
fruitObjInObj[type] = count; // Adds property to fruit obj
return theObj; // Gives theObj back to `reduce` for next loop
}, obj); // Tells `reduce` to use obj as theObj on first loop
console.log(obj);
Please see my Fiddle which includes all the code that follows.
My apologies if this question has been answered before. I found similar questions on here about grouping by property, but I did not find an example where the result was still an array of objects.
I'm starting with this data format:
const originalData = [
{
"groupId": 0,
"color": "red",
"shape": "circle"
},
{
"groupId": 1,
"color": "green",
"shape": "square"
},
{
"groupId": 1,
"color": "orange",
"shape": "hexagon"
},
{
"groupId": 1,
"color": "purple",
"shape": "triangle"
},
{
"groupId": 2,
"color": "aqua",
"shape": "diamond"
},
{
"groupId": 2,
"color": "blue",
"shape": "trapezoid"
}
];
And I would like to transform it into a new array of objects, grouped by groupId property value:
const desiredData = [
{
"groupId": 0,
"items": [
{
"color": "red",
"shape": "circle"
}
]
},
{
"groupId": 1,
"items": [
{
"color": "green",
"shape": "square"
},
{
"color": "orange",
"shape": "hexagon"
},
{
"color": "purple",
"shape": "triangle"
}
]
},
{
"groupId": 2,
"items": [
{
"color": "aqua",
"shape": "diamond"
},
{
"color": "blue",
"shape": "trapezoid"
}
]
}
];
This reduce function (which I found on MDN) is the closest I was able to come to transforming my data. My experience with transforming data in Javascript is limited, and I am not sure how to add fields (like group) during the transformation process. Also, the result is an object, not an array of objects.
const actualFormattedData = originalData.reduce((acc, obj) => {
let key = obj['groupId'];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
Output from the reduce function:
{
"0": [
{
"groupId": 0,
"color": "red",
"shape": "circle"
}
],
"1": [
{
"groupId": 1,
"color": "green",
"shape": "square"
},
{
"groupId": 1,
"color": "orange",
"shape": "hexagon"
},
{
"groupId": 1,
"color": "purple",
"shape": "triangle"
}
],
"2": [
{
"groupId": 2,
"color": "aqua",
"shape": "diamond"
},
{
"groupId": 2,
"color": "blue",
"shape": "trapezoid"
}
]
}
The ultimate goal is to map the array of objects in React. I know I can use Object.entries and array indices to achieve a similar result with actualFormattedData as-is, but it would be ideal if I could first make actualFormattedData look exactly like desiredData.
This should work:
const dict = originalData.reduce((acc, obj) => {
let groupId = obj['groupId'];
delete obj.groupId;
if (!acc[groupId]) {
acc[groupId] = { // here is where we add the fields you wanted
groupId,
items: []
};
}
acc[groupId].items.push(obj);
return acc;
}, {});
// turn this into an array, just getting the values of the fields in the dictionary
const actualFormattedData = Object.values(dict);
Here is your fiddle solution
https://jsfiddle.net/07n9ks86/
and the crucial code for it (n2):
const formattedData = originalData.reduce((acc, curr) => {
console.log(acc)
const index = acc.findIndex(x => x.group === curr.group);
if (index > 0) {
acc[index] = {
...acc[index],
items: [...acc[index].items,
{
'color': curr.color,
'shape': curr.shape
}
]
}
} else {
acc.push({
group: curr.group,
items: [{
'color': curr.color,
'shape': curr.shape
}]
})
}
return acc;
}, []);
A simple solution can be achieved with a single call to Array#reduce(), as detailed in the code snippet below.
Just a note that this solution emphasises simplicity over efficiency, and would tend to not be suitable for very large input arrays:
const originalData=[{groupId:0,color:"red",shape:"circle"},{groupId:1,color:"green",shape:"square"},{groupId:1,color:"orange",shape:"hexagon"},{groupId:1,color:"purple",shape:"triangle"},{groupId:2,color:"aqua",shape:"diamond"},{groupId:2,color:"blue",shape:"trapezoid"}];
/* Use reduce to iterate and transform originalData array to desired result */
const desiredData = originalData.reduce((result, item) => {
/* The group item to add from this iteration */
const groupItem = { color : item.color, shape : item.shape };
/* Search for item that already exists with matching group id */
const existingGroup = result.find(resultItem => resultItem.groupId === item.groupId);
if(existingGroup) {
/* Add item to group if found */
existingGroup.items.push(groupItem);
}
else {
/* Add group with item if not group found */
result.push({
groupId : item.groupId,
items : [ groupItem ]
});
}
return result;
}, []);
console.log(desiredData);
Hope that helps!
Another simplest method to group by property name can be using lodash.
let groupedData = _.groupBy(rawData, dataObj => dataObj.propertyToGroupBy)
Where groupedData is the result you are looking for, rawData is the original data and propertyToGroupBy is the property of the object with which you want to group.
You can check this answer.
Here is an easy to understand solution:
const originalData = [
{
"groupId": 0,
"color": "red",
"shape": "circle"
},
{
"groupId": 1,
"color": "green",
"shape": "square"
},
{
"groupId": 1,
"color": "orange",
"shape": "hexagon"
},
{
"groupId": 1,
"color": "purple",
"shape": "triangle"
},
{
"groupId": 2,
"color": "aqua",
"shape": "diamond"
},
{
"groupId": 2,
"color": "blue",
"shape": "trapezoid"
}
];
const data = [];
const dataObjIndex = id=>{
for(let i=0,l=data.length; i<l; i++){
if(data[i].groupId === id){
return i;
}
}
return -1;
}
originalData.forEach(o=>{
let i = dataObjIndex(o.groupId);
if(i === -1){
i = data.length; data.push({groupId:o.groupId, items:[]});
}
data[i].items.push({color:o.color, shape:o.shape});
});
console.log(data);