Working on a React app and have a this.state.filesAccepted which is an array of objects. It looks like this:
I also have an array of strings called filenames that looks like the following:
I'd like to compare the two and if there is a match, the object should be removed from the array in this.state.filesAccepted. For example, if a string in filenames ("eicartest1") matches the key in filesAccepted (key: "eicartest1"), it should remove that object from the array.
There may be a more efficient and cleaner way of doing this, but for the comparison, I think I need to do two loops like the following:
_.map(filenames, f => {
_.map(this.state.filesAccepted, fa => {
if (f === fa.key) {
delete entire object from array;
}
});
});
How should I be handling the delete? Is there a more efficient way to make this comparison besides map twice?
The following should work:
this.state.filesAccepted.filter(
file=>!filenames.includes(file.key)
)
That results in an array that only has items where the src is not in filenames
To create a new state with the new filesAccepted you can do:
this.setState({
...this.state,
filesAccepted:this.state.filesAccepted.filter(
file=>!filenames.includes(file.key)
)
})
You can use Array.prototype.filter() to remove unmatched items
const filesAccepted = this.state.filesAccepted.filter(obj => !_.includes(filenames, obj.key));
this.setState({filesAccepted});
Related
does anyone know how I can remove a surrounding array from an array of objects? In my case, I only have one object in this array. [{"id":"6","email":"test#test.com"}] Also, would the solution work in the case of multiple objects in the array? Thanks!
You have an array of objects. That's great, because it's the easiest way to store and manipulate lists of records.
You can use array methods like .map that allow you to treat each record separately, telling it what to do individually with each element. That's also great, because it basically "removes the element from the array" while still processing the whole array, which is what I think you're after.
Simple example to create a dropdown:
const data = [{"id":"6","email":"test#test.com"}, {"id":"12","email":"test2#test.com"}];
const drawEmailDropdown = () => {
let options = data.map(d => `<option value='${d.id}'>${d.email}</option>`);
return `<select>` + options.join("") + `</select>`;
};
document.querySelector("#container").innerHTML = drawEmailDropdown();
<div id="container"></div>
I learn Javascript and read and understand how the includes works to test if a value exists in an array.
My problem comes when I have an Array of items that look like this this:
state = { focused: null, files: [] };:
The image show this here:
When I add a new newFile and it's the same it should not add it ok but the evaluation,
if (newFile && !files.includes(newFile)) {.. always say false so how to test for this do I have to test on individual values inside newFiles?
Array.includes will not do a deep comparison between object, only a shallow one comparing references. This way even objects that have same values they would fail on test because they have different references.
In your case you could compare id, which should be unique for each object. You can use Array.every that checks if all values pass in the test. This way you want to check that every file id doesn't match newFile id:
if (newFile && files.every(({id}) => newFile.id !== id))
Array.includes does reference comparison for Array or Object, so instead you can use Array.filter
if (newFile && newFile.filter(e => { /*Comparison logic */ }).length > 0)
I have an array of ObjectIds like this:
[ 5cd295fbc53f626fd9d70894,
5cb0624945111f1c5fdf2527,
5cc290f5b90fc527c1e46efd,
5cd6737f294e7b6ec3d9420f,
5cd295fbc53f626fd9d70894,
5cb0624945111f1c5fdf2527,
5cc290f5b90fc527c1e46efd,
5cd6737f294e7b6ec3d9420f,
5cd295fbc53f626fd9d70894 ]
I need to convert each Objectid into strings.
I have tried toString() and JSON.stringify(). But toString() splits every character into a string and JSON.stringify() does not affect the array.
Actually I was working on finding the unique Ids in the array. I have tried many functions to get unique elements, but they seem to work only with numbers and strings and not ObjectIds.
On finding the type of element, it displayed it as an object.
So I'm trying to convert the array of objects to array of string, so that I can easily use one of the functions to get the unique elements.
Expected output would be like this:
[ "5cd295fbc53f626fd9d70894",
"5cb0624945111f1c5fdf2527",
"5cc290f5b90fc527c1e46efd",
"5cd6737f294e7b6ec3d9420f",
"5cd295fbc53f626fd9d70894",
"5cb0624945111f1c5fdf2527",
"5cc290f5b90fc527c1e46efd",
"5cd6737f294e7b6ec3d9420f",
"5cd295fbc53f626fd9d70894" ]
You could do it with map. Call toString for each element in the array and returning them in a new array as strings.
For example:
const stringsArray = objectIds.map(x => x.toString());
Then the most efficient way to get unique results in an array would be to put them on a Set. So it would look like the following:
const uniqueStrings = [...new Set(stringsArray)];
You can use map and pass the String constructor as a function, which will convert each Objectid into a string:
Objectids.map(String) //=> [ "5cd295fbc53f626fd9d70894",
// "5cb0624945111f1c5fdf2527", ...
This will not mutate Objectids. It will return a new array.
It's not a answer to convert the ObjectId to string.
But if you want to find only the unique ObjectId, you can use the set object in JavaScript
According to MDN :
The Set object lets you store unique values of any type, whether primitive values or object references.
You can do:
const set1 = new Set([your array]);
I am having an array of objects where all objects have the same keys except the last object. Think like array have values and to denote all these values as a whole I have a key I am pushing the key at last along with the values in the array.
homeTask is a list of object which is the values and homeTaskKey is the key to represent the homeTask
res.data.resultSet.homeTask.forEach(element => {
var singleEvent={
task:'',
taskDuration:'',
status:'',
};
singleEvent.task=element.task;
singleEvent.taskDuration=element.taskDuration;
singleEvent.status=element.status;
newEvents.push(singleEvent);
});
newEvents.push(res.data.resultSet.homeTaskKey);
addEvent(newEvents);
}
addEvent is props method of parent component where I am setting the array to state variable name as events which is array type.
When I iterate over events using map I want to skip the last object since it does not have keys like task, taskDuration and status. Therefore it won't give any problem when I fetch those values.
events.slice(0, events.length-1).map(<function>);
this will ignore the last element and all n-1 entries will be fed to map
UPDATE:
the array name is events not event therefore it should be events.length
You could still use map, but simply pop the last element off once the map completes. For example:
const newEvents = homeTask.map(({ task, taskDuration, status }) => ({
task, taskDuration, status
}))
newEvents.pop()
addEvent(newEvents)
Or just replace the last item with your taskkey, as you know the last item will be junk:
newEvents[newEvents.length - 1] = res.data.resultSet.homeTaskKey
Or just slice the array prior to mapping, and then push the taskKey at the end like you were doing. slice is safe to perform on your prop, as it shallow copies.
Or most importantly, ask yourself why you have this entirely weird data structure that has the key appended on the end. Perhaps rethink your data and not create this problem for yourself in the first place.
res.data.resultSet.homeTask.forEach((element,index) => {})
second param to function is index you, can use this to identify the second last element by comparing it with total length of array.
hmm you can try with this
res.data.resultSet.homeTask.forEach(element => {
if(!element.task)
return false;
...bla bla bla
}
The map() method creates a new array with the results of calling a function for every array element.
So it creates an array of same length from source array.
What you need is filter()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Something like this;
const tasks = res.data.resultSet.homeTask.filter((element) => {
const { task, taskDuration, status } = element;
return task && taskDuration && status;
});
I'm trying to replace array elements (generic objects) with their alternatives (specific Objects), but objects within the original array remain unchanged.
class SpecificObject{
}
this.Objects = [{},{}];
this.Objects.map((signer,index) => {
//convert json generics to js objects
this.Objects[index] = new SpecificObject(signer);
});
console.log(this.Objects);
Not sure if the code snippet illustrates the problem correctly, but what i expect to see is:
[
SpecificObject{},
SpecificObject{}
]
I even tried cloning the original object to do the iteration but it didn't help. Must be missing something stupid. Is there a way to achieve what i need with lodash?
Edit(followed the answer advise):
Now i do the following:
console.log('signers-before', this.Signers);
this.Signers.map(signer => new SigningTableSigner(signer));
console.log('signers-after',this.Signers);
And this is what i get in my log(object still remain generic):
Edit2
Oops, i forgot the assignment. this.Signers =
now like this everything works as expected:
console.log('signers-before', this.Signers);
this.Signers = this.Signers.map(signer => new SigningTableSigner(signer));
console.log('signers-after',this.Signers);
There is no need to modify the collection while you are iterating it. Just return the object from the map.
this.Objects = this.Objects.map((signer,index) => new SpecificObject(signer));
Map is used when you wants to return an array. You can just use forEach for what you are trying to do. But I think this will look better
this.Objects = this.Objects.map(signer => new SpecificObject(signer))
You don't use map correctly. You should be just returning objects inside arrow functions. map actually returns new array, which contains elements which were created by applying function you have provided. Because of that you also have to reassign result ot this.Objects.
this.Objects = this.Objects.map(signer => {
//convert json generics to js objects
return new SpecificObject(signer);
})