if I have an array like this:
const[arr,setArr] = React.useState([
{label:"dummy01",id:2},
{label:"dummy02",id:5},
])
is there anyway to update arr with such array:
const newArray = [{label:'dummy Altered01',id:2},{label:'different',id:10},{label:'different 02',id:55}}
what I expect to have an array like this :
[
{label:"dummy Altered01",id:2},
{label:"dummy02",id:5},
{label:'different',id:10},
{label:'different 02',id:55}
]
as you can see the object with the id of 2 is updated and other new objects are added to the array without erasing previous dummy02.
I don't know how should I compare id inside of two different arrays
I know this is not the best answer, so here's what I got
let listOfIds = newArray.map(item => item.id)
newArray = newArray.concat(arr.filter(item => !listOfIds.includes(item.id)))
First you map the newArray into a list of IDs.
Then newArray concatenates with the filtered original array (i.e. the array now doesn't have any items with ids in common with the latter )
Finally you update the state by setArr(newArr)
Hope this answers your question
Lets consider
a = [{label:"dummy01",id:2},{label:"dummy02",id:5}]
and new array is
b= [{label:'dummy Altered01',id:2},{label:'different',id:10},{label:'different 02',id:55}]
Now perform itearation over new array
b.forEach((item)=>{
let index = a.findIndex((x)=>x.id == item.id)
if(index > -1){
a[index].label = item.label
}
else
a.push(item)
})
console.log(a)
In my code I have an element, and I want to have it in an array: either the array already exists and then I push my element, or it doesn't and in that case I create the array with this only element:
if (arr) {
arr.push(elt);
} else {
arr = [elt];
}
I'm sure there is a better way to do this. I looked into spreading and nullish coalescing operator, but I didn't find any correct syntax.
Does anybody have an idea on how I could write my lines with a nicer syntax?
Thanks in advance.
You can use the expression arr || [] to return an array which is either arr if arr is defined already or [] otherwise. Then you can simply concat the new value to it:
arr = (arr || []).concat([elt])
Note the new value needs to be enclosed in [] to prevent elt values which are arrays from being flattened.
You can check if an array exists by testing if it is false-y. Thus, you can create an array if it doesn't already exist with
arr = (arr || []);
From there you can just push your new element:
arr = (arr || []);
arr.push(elt);
See the below code:
if (arr && arr.length > 0) {
arr.push(elt);
//or can use spread operator
arr = [...arr, elt];//this should work if I am not wrong
} else {
arr = [elt];
}
It is somewhat similar but I guess it should work fine and is a general pattern.
I am having a filtering problem..
objArray is the array that needs to be filtered.
selectedNames is an array that contains the values that I want to find in objArray.
I need to fetch all objects that have one or more values from selectedNames in their "names" property (an array) .
The output I am trying to get is :
let result = [{names:["A","B","C","D"]},
{names:["A","B"]},
{names:["A","D"]}
]
Here is a simplified version of my code:
let objArray = [{names:["A","B","C","D"]},
{names:["C","D"]},
{names:["C","D","E"]},
{names:["A","B"]},
{names:["A","D"]}
]
let selectedNames = ["A","B"]
result = this.objArray .filter(obj => {
return this.selectedNames.includes(obj.names)
}
My code seems to work fine if names attribute was a single value and not an array. But I can't figure out how to make it work on an array.
Any help is more than welcome
You could do something like this. Filtering the array based on the names property having 'some' value be included in the selectedNames array.
...
objArray.filter(obj => obj.names.some(name => selectedNames.includes(name)));
[Edit] As #RadicalTurnip pointed out, this is not performant if the selectedNames is too large. I would suggest that you use an object. E.x
...
const selectedNamesMap = selectedNames.reduce((p,c) => ({...p, [c]: true}), {});
objArray.filter(obj => obj.names.some(name => selelectedNamesMap[name]));
Overkill, but if the arrays are really large (millions of elements) then you are better of using regular for loop and not array methods.
This result is not performant scaled up, but I don't know that there is any way to ensure that it will be performant unless you know more information (like the names are already sorted). That being said, you just missed one more piece of logic.
result = this.objArray.filter(obj => {
let toReturn = false;
obj.names.forEach(name => {
if (this.selectedNames.includes(name))
toReturn = true;
};
};
return toReturn;
};
I have an Array like this: var obj = [{x:4, y:5}, {x:6, y:2}, ...] and I'm trying to delete one of the inside objects (properties) based on the x.
this is How I'm trying to do this:
obj.forEach(function (child){
if(child.x === 4){
obj.destroy(child)
}
});
But it's not working and i get
obj.destroy is not a funtion
I also tried obj.splice(child) but it just mess up the array. so what am doing wrong here?
Also is there a better way to do this by not having to loop through all of Array property every time?
You can just use filter on the array: e.g.
let arrayToFilter = [ {x:4, y:5}, {x:6, y:2}];
const valueToFilter = 4;
var filteredArray = arrayToFilter .filter((o) => {
return o.x !== valueToFilter;
});
console.log(filteredArray);
forEach() works on array.
If obj is an array, you can simply use filter() to remove the unwanted object from the array:
var obj = [{x:4, y:5}, {x:6, y:2}]
obj = obj.filter(c => c.x !== 4)
console.log(obj);
You perhaps, have an array as obj because the one you posted in the question is simply invalid syntax.
Moreover, you can use Array#findIndex to get the index of the matching element first, and then splice that index from the array.
var obj = [{x:4, y:5}, {x:6, y:2}];
var index = obj.findIndex(item => item.x === 4);
obj.splice(index, 1);
console.log(obj);
i'm assuming your trying to filter out objects in an array which have an x that matches a given value. If thats the case, you should probably use the filter method.
So assuming thats what you mean you could do the following
obj = obj.filter(function (child){
if(child.x !== 4){
return obj
}
});
// shorter
obj = obj.filter( child => child.x !== 4 );
In this case, only the objects which do not have the value of 4 will be available to you in the obj variable. And all other objects (assuming there are no other references in your code) will be garbage collected.
I need to remove elements from a json string returned by an AJAX call.
I'm not sure how to loop through the string and remove all elements where the value i NULL.
My json looks like this.
[
{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},
{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},
{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},
{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},
{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}
]
I thought I might do something like this for every key but i would prefer a generic function:
if(json[index].Strength == null){
json.splice(index,1);
}
You can parse json with JSON.parse method and then use filter() method on that array.
const json = '[{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}]'
const data = JSON.parse(json).filter(o => o.Strength != null)
console.log(data)
If you want to remove elements where some property has value of null you can use some method inside filter.
const json = '[{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}]'
const data = JSON.parse(json).filter(o => {
return !Object.keys(o).some(k => o[k] == null)
})
console.log(data)
Use filter:
const newJson = json.filter(item => item.Strength !== null)
If you prefer a generic function, Lodash is the best option.
PickBy picks up properties from an object, based on a Predicate.
Here predicate is Identity, which means, pickup non null properties from the object.
var jsonResponse = '[{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}]';
var responseArr = JSON.parse(jsonResponse);
// Only lines that matter
responseArr = _.map(responseArr, function(obj) {
return _.pickBy(obj, _.identity);
});
console.log("Array of Objects: ", responseArr);
console.log("JSON: ", JSON.stringify(responseArr));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>
Put the above mentioned script tag just before closing tag of your html page.
So just loop through the whole array response using map, and apply PickBy on each object of the array, and you have yourself an array of sparse objects.
Try Array filter() method with ES6 Arrow function.
Demo
var jsonObj = [
{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},
{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},
{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},
{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},
{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}
];
var res = jsonObj.filter(elem => elem.Strength !== null);
console.log(res);