I've a little array problem I'm going round and round in loops with.
I have a number of check boxes, each checkbox has a specific object.
On checking a checkbox I want to iterate over the array and if the id of the checkbox (object) does not match any other items in the array, push to the array.
I have the following, which pushes the checkbox object for every item that doesn't match it's id. So I end up with multiple objects of the same ID.
mapMarkers.map(marker => {
if(markerID !== marker[0].id) {
mapMarkers.push(markerObject)
};
});
Any help to get my thinking on this straight would be appreciated.
For context here's the project its from. Lines 281
https://codepen.io/sharperwebdev/pen/PQvMqR?editors=0011
The Array#filter method would be more appropriate for this. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const filteredMarkers = mapMarkers.filter(marker => markerID !== marker.id);
Then use filteredMarkers (mapMarkers isn't mutated, which is a better practice).
Related
I am trying to iterate over an array of array objects to de-dupe and sort the data within each. The function onlyUnique returns unique values in an array. The problem is, it doesn't work as intended.
arr_lists = [arr_1, arr_2, arr_3, arr_4, arr_5, ...]
for (var list_obj of arr_lists) {
list_obj = list_obj.join().split(',').filter(onlyUnique);
list_obj.sort();
Logger.log(list_obj);
}
The logger results show true (i.e. they are what I am looking for), but the original array is unchanged, although I think it should have been updated.
I've tried assigning the filtered array to a new array... nope.
I know that I could add a thousand lines of code to achieve the results, but that seems silly.
I suspect it's something obvious.
You can simply achieve it by using Set data structure to remove the duplicates and Array.sort() compare function to sort the elements in an array.
Live Demo :
const arr_lists = [[2,3,5,6], [7,2,5,3,3], [1,5,3], [4,7,4,7,3], [1,2,3]];
arr_lists.forEach((arr, index) => {
arr_lists[index] = [...new Set(arr)].sort((a, b) => a -b);
})
console.log(arr_lists);
I'm currently using a method to try to filter some arrays, the method is almost working but I can't seem to access the exact values -
I make a call and add each returned array into a bigger array, these arrays will then be assigned a productId and maybe some data, i am appending the productIds using this:
data.push({'productId': product.id});
Which unfortunately adds a new object to the array which means my function below doesnt work unless the productId is in the first object of each array:
let matchedArray = data.flatMap(arr => arr.filter(obj => obj.productId == id))
What I need to do is filter the array down to the subarray that matches the productId and ID and also that has some of the fields of data such as 'name' - so it checks that the name isnt empty.
The data set looks like this (array of subarrays)
id = 12345
data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"africa soul
2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Ev
ent","members":null},{"productId":"12345"}],[],[],[],[],[],[],
[],[],[],[],[]]
As you can see the productId is appended to the array but isnt now working with my filter method, i need to filter for the right array that has matching ID's and at least one of the fields are also existing. I either need to change the way the productId is manually appended, or change the filter method?
Thanks so much if you can help
If you want to filter all the arrays which have some object which have a productId equal to a given value:
let data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"africa soul 2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Event","members":null},{"productId":"12345"}],[],[],[],[],[],[],[],[],[],[],[]],
id = "12345";
let filtered = data.filter(arr => arr.some(a => a.productId === id))
console.log(filtered)
If you want to get the first match, use find instead of filter
It's quite possible I am going about this the wrong way, but I have a primary array that i need to filter if any of it's objects values exist in two other arrays. I am trying to use a combination of filter() and some() but what I have right now is not working.
const milestones = <FormArray>this.piForm.get('_milestones');
if (this.piById) {
milestonesToCreate = milestones.value
.filter(milestone => !this.piById.milestones.some(item => item.milestoneId === milestone.milestoneId));
milestonesToDelete = this.piById.milestones
.filter(milestone => !milestones.value.some(item => item.milestoneId === milestone.milestoneId));
milestonesToUpdate = milestones.value
.filter(milestone => milestones.value
.some(item =>
item.milestoneId === milestonesToCreate.milestoneId && milestonesToDelete.milestoneId));
}
In the code above milestonesToUpdate should be a the filtered results where the array consists of objects that are not in milestonesToCreate and milestonesToDelete
Hopefully I've explained this well enough.
ADDED SAMPLE MILESTONES ARRAY
milestones = [
{
"milestoneId": 0
}
]
Firstly, it looks like your problem is just a misunderstanding of boolean checks in your final call to some().
You have put:
item.milestoneId === milestonesToCreate.milestoneId && milestonesToDelete.milestoneId
Which is the same as saying, where item.milestoneId equals milestonesToCreate.milestoneId AND milestonesToDelete.milestoneId exists. I expect that you are just trying to check if the current value exists in both arrays.
it's better to achieve that in single pass:
put all elements to elementsToUpdate, copy all elements from your this into elementsToDelete
iterate through elementsToUpdate, once some item does not exist in another list, move that element into elementsToCreate
if element exists in both, remove it from elementsToDelete.
finally you will get 3 lists you need.
And you can even speed up code more if instead of using arrays you use hash(old good {}) where id are used as keys. Then check "if element is here" would be as easy as item in elementsToUpdate instead of iterating all the elements each time
Regarding this post (Remove Duplicates from JavaScript Array) on creating a new array of unique values from another array.
Code in question:
uniqueArray = myArray.filter(function(elem, pos) {
return myArray.indexOf(elem) == pos;
})
Using this as the test data:
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
Desired result is an array with only unique values:
var unique_names = ["Mike","Matt","Nancy","Adam","Jenny","Carl"];
Where I'm at:
I understand that filter will run a function on each member of the array, and that elem is the element being reviewed, and that pos is its index. If something causes that function to return false, then that element will not be included in the new array. So walking through it, this happens:
Is myArray.indexOf("Mike") the same as 0? Yes, so add "Mike" to the new array.
Is myArray.indexOf("Matt") the same as 1? Yes, so add "Matt" to the new array.
Is myArray.indexOf("Nancy") the same as 2? Yes, so add "Nancy" to the new array.
[repeat for all elements. All pass.]
Basically I don't get why the 2nd Nancy would evaluate to false.
The indexof is the index of the first appearance of the element, so the second Nancy would get the index of the first Nancy, and would be filtered out.
6) Is myArray.indexOf("Nancy") the same as 5? No (it's 2, just like it step 3), so skip the duplicated "Nancy".
indexOf gives you the first occurrence of the item.
OK, I'm missing something here and I just can't seem to find it because the logic seems correct to me, but I'm certain I'm not seeing the error.
var VisibleMarkers = function() {
var filtered = _.reject(Gmaps.map.markers, function(marker) {
return marker.grade != $('.mapDataGrade').val() && !_.contains(marker.subjects,$('.mapDataSubjects').val())
});
return filtered
}
I'm using underscore.js and jQuery to simplify my javascript work.
So right now, I'm checking by means of selects which data gets to be rejected and then I display the filtered markers on the (google) map (if it helps at all, this is using gmaps4rails which is working perfectly fine, its this bit of javascript that's making me lose the last of the hairs on my head).
Currently, the code functions 100% correctly for the ".mapDataGrade" select, but the ".mapDataSubjects" isn't. Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
Can someone see what I'm doing wrong?
If there's more info that needs to be included, please let me know.
This is on plain javascript on a RoR application using gmaps4rails
Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
_.contains compares a values, but it sounds like you want your iterator to compare a value to an object's "id" property. For that, _.some would work; it's like contains, except that, instead of comparing values, you can write the comparison as a function:
Returns true if any of the values in the list pass the iterator truth test.
Here's how you'd use it:
!_.some(marker.subjects, function(subject) {
return subject.id == $('.mapDataSubjects').val();
})
If I'm right, the whole line should be like this:
return marker.grade != $('.mapDataGrade').val() &&
// check that none of the subjects is a match
!_.some(marker.subjects, function(subject) {
// the current subject is a match if its ID matches the selected value
return subject.id == $('.mapDataSubjects').val();
});