JS: Iterate over an array of objects to update object - javascript

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);

Related

Array filter method to match IDs and check properties exist

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

filter an array based on multiple arrays using some()

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

Push to an array if id value is not found

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).

How can I push a null value into the start of an array?

I have this code that fetches data and puts it into an array:
this.$httpGetTest(this.test.testId)
.success(function (data: ITestQuestion[]) {
self.test.qs = data;
});
It works and populates the array starting with self.test.qs[0].
However many times my code references this array (which contains a list of questions 1...x)
I must always remember to subract 1 from the question number and so my code does not look clear. Is there a way that I could place an entry ahead of all the others in the array so that:
self.test.qs[0] is null
self.test.qs[1] references the first real data for question number 1.
Ideally I would like to do this by putting something after the self.test.qs = and before data.
Push values at start of array via unshift
self.test.qs.unshift(null);
You need to use Splice(), It works like:
The splice() method changes the content of an array, adding new elements while removing old elements.
so try:
self.test.qs.splice(0, 0, null);
Here mid argument 0 is to set no elements to remove from array so it will insert null at zero and move all other elements.
Here is demo:
var arr = [];
arr[0] = "Hello";
arr[1] = "Friend";
alert(arr.join());
arr.splice(1,0,"my");
alert(arr.join());
You can start off with an array with a null value in it, then concat the questions array to it.
var arr = [null];
arr = arr.concat(data);
You could do something like:
x = [null].concat([1, 2, 3]);
Though there isn't anything wrong with doing something like:
x[index-1]
I'd prefer it to be honest, otherwise someone might assume that the index value returned is 0 based.

Remove element from array, using slice

I am trying to remove a element from my array using slice, but i can't get it to work, look at this piece of code.
console.log(this.activeEffects); // Prints my array
console.log(this.activeEffects.slice(0,1)); // Remove from index 0, and remove one.
console.log(this.activeEffects); // Prints array again, this time my element should be gone
Result of this is.
So what is get from this is, at first the array is whole, as it should be. Then its prints what is sliced of the array. Finally the third should be empty? or?
function removeItemWithSlice(index) {
return [...items.slice(0, index), ...items.slice(index + 1)]
}
Slice will create a new array. We create two arrays: from beggining to index and from index+1 to end. Then we apply the spread operator (...) to take the items of those arrays and create a new single array containing all the items we care. I will paste an equivalent way if you don't like the one liner:
function removeItemWithSlice(index) {
const firstArr = items.slice(0, index);
const secondArr = items.slice(index + 1);
return [...firstArr , ...secondArr]
}
I believe you're looking for splice. From W3 Schools:
The splice() method adds/removes items to/from an array, and returns the removed item(s).
Take a look at the example on that page; the use case there is similar to what you want to achieve.
EDIT: Alternative link to MDN, as suggested by Nicosunshine; much more information about the command there.
a.slice(0, index).concat(a.slice(index + 1))
.slice does not mutate the array, you could use .splice() to remove the item at index i in the array:
this.activeEffects.splice(i, 1)
This is what I was able to come up with :
var newArray = oldArray.slice(indexOfElementToRemove+1).concat(oldArray.slice(0,indexOfElementToRemove));
Array.prototype.slice()...
does not alter the original array, but returns a new "one level
deep" copy that contains copies of the elements sliced from the
original array. Elements of the original array are copied into the new
array as follows:
Whereas Array.prototype.splice()...
Changes the content of an array, adding new elements while removing old elements.
This example should illustrate the difference.
// sample array
var list = ["a","b","c","d"];
// slice returns a new array
console.log("copied items: %o", list.slice(2));
// but leaves list itself unchanged
console.log("list: %o", list);
// splice modifies the array and returns a list of the removed items
console.log("removed items: %o", list.splice(2));
// list has changed
console.log("list: %o", list);
Look at here :
http://www.w3schools.com/jsref/jsref_slice_array.asp
You can see that the slice method select object et throw them into a new array object ^^ So you can't delete an object like this, may be you can try a thing like this :
var a = ["a","b","c"]; (pseudo code)
/* I wan't to remove the "b" object */
var result = a.slice(0,1)+a.slice(2,1); /* If you considers that "+" is a concatenation operator, i don't remember if it is true... */

Categories