loop multiple arrays javascript - javascript

I have the following structure:
objet and arrays
I would like to determine if the object has an array with values ​​and if so, save those values ​​by saving those values ​​in another arryar that I will then go through, I have the following up to now:
if (resp.Boutique.length >= 1) {
for (let index = 0; index < resp.Boutique.length; index++) {
this.general.push(resp.Boutique[index]);
}
}
if (resp.Curso.length >= 1) {
for (let index = 0; index < resp.Curso.length; index++) {
this.general.push(resp.Curso[index]);
}
}
if (resp.Deporte.length >= 1) {
for (let index = 0; index < resp.Deporte.length; index++) {
this.general.push(resp.Deporte[index]);;
}
}
but if you have more 'if' elements, I do not think it's the best way.
Any recommendation?

If the properties always contain arrays, then there's no need to test for their length before iterating over them; if they have length 0, no iterations will be performed, so nothing will be pushed to this.general.
But there's a better way - you can simply spread each possibly-empty array into this.general, in a single line:
this.general = [...resp.Boutique, ...resp.Curso, ...resp.Deporte];
If the properties of resp contain only the arrays you want to include in .general, then iterate over the values of resp instead:
this.general = [].concat(...Object.values(resp));

arr.concat(arr1, arr2, arr3 ...)
let arr = [1, 2, 3, 4];
let arr1 = [4, 5, 6, 7];
let arr2 = [7, 8, 9, 10]
console.log(arr.concat(arr1, arr2));

Related

Javascript for loop and splice function

Good day, I have been trying to solve JS problem where I have an array a = [1, 1, 1, 2, 1, 3, 4]. I have to loop through an array and remove every three elements ie (1,1,1) do some logic, then the next three (1,1,2), and so on.
I have used for loop and splice
a = [1, 1, 1, 2, 1, 3, 4]
tuple = ()
for(j=0; j < a.length; j++){
tuple = a.splice(j, 3)
}
However, loop would not go beyond first round of (1,1,1).
What would be the correct way to loop through this array and remove sets of every three elements.
thank you.
Splice return removed elements from base array in given range. You probable want to use slice which only copy them and doesn't change primary array. You can also check this solution.
let a = [1, 1, 1, 2, 1, 3, 4];
for (j = 0; j < a.length; j++) {
if ( j < a.length - 2 ) {
const touple = [ a[j], a[j+1], a[j+2] ]
console.log( touple )
}
}
splice changes the original array and that must be causing your issue.
So, you can use slice which returns a shallow copy of a portion of the original array (without modifying the original array):
const a = [1, 1, 1, 2, 1, 3, 4]
const doLogic = (arr) => {
console.log(JSON.stringify(arr)) // JSON.stringify is only for one-liner print. You can ignore it.
}
for (let i = 0; i < a.length - 2; i++) {
const picked = a.slice(i, i + 3)
doLogic(picked)
}
Or this, if you want to pick the full array when length is less than 3:
if (a.length < 3) {
doLogic(a)
} else {
for (let i = 0; i < a.length - 2; i++) {
const picked = a.slice(i, i + 3)
doLogic(picked)
}
}

Efficient algorithm for removing items from an array in place

I'm looking for an efficient JavaScript utility method that in O(n) will remove a set of items from an array in place. You can assume equality with the === operator will work correctly.
Here is an example signature (written in TypeScript for type clarity)
function deleteItemsFromArray<T>(array: T[], itemsToDelete: T[]) { ... }
My thought is to do this in two passes. The first pass gets the indexes that need to be removed. The second pass then compacts the array by copying backwards from the current index being removed through the next index being removed.
Does anyone have code like this already handy or a more efficient way to do this?
P.S. Please don't point out the filter function as that creates a copy of the array, it does not work in place.
Iterate over the array, copying elements that aren't in itemsToDelete to the next destination index in the array. When you delete an element, you don't increment this index.
Finally, reset the length of the array at the end to get rid of the remaining elements at the end.
function deleteItemsFromArray(array, itemsToDelete) {
let destIndex = 0;
array.forEach(e => {
if (!itemsToDelete.includes(e)) {
array[destIndex++] = e;
}
});
array.length = destIndex;
}
const array = [1, 2, 3, 4, 5, 6, 7];
deleteItemsFromArray(array, [3, 5]);
console.log(array);
function deleteItems(array,items){
let itemsToDelete=0;
let indexToSwap = array.length-1;
for(let i = array.length-1,currItem ; i>=0 ; i--){
if(items.includes(array[i]){
[array[i] , array[indexToSwap]] = [array[indexToSwap] , array[i]];
--indexToSwap;
++itemsToDelete;
}
}
array.splice(array.length-itemsToDelete,itemsToDelete);
}
This should work, I haven't tested it.
The idea is to swap the elements to delete to the end of the array. You can remove them at the end how I do in my code or you could use too the pop() function every time.
It's very, very simple - transform itemsToDelete to a Set. This ensures O(1) lookups. Then walk through the array backwards and remove items with Array#splice. In total, that gives you a linear O(n+m) time complexity:
function deleteItemsFromArray<T>(array: T[], itemsToDelete: T[]) {
const setToDelete = new Set(itemsToDelete);
for (let i = array.length - 1; i >= 0; i--) {
const item = array[i];
const shouldBeDeleted = setToDelete.has(item);
if (shouldBeDeleted) {
array.splice(i, 1);
}
}
}
You can save the conversion step if you just make the function accept a set to begin with and change the signature to:
function deleteItemsFromArray<T>(array: T[], itemsToDelete: Set<T>)
function deleteItemsFromArray(array, itemsToDelete) {
for (let i = array.length - 1; i >= 0; i--) {
const item = array[i];
const shouldBeDeleted = itemsToDelete.has(item);
if (shouldBeDeleted) {
array.splice(i, 1);
}
}
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
deleteItemsFromArray(
arr, new Set([1, 3, 5, 7, 8, 9])
)
console.log(arr);
Using copyWithin method will be helpful here.
method 1
Traverse from last index to first index, when ever we find the item to remove just copy/move elements to left.
Though we will be doing times the copy/move, But still have some unnecessary moving elements.
method 2
Traverse from first index to last index, when ever we find the item to remove, identify the group of elements to copy/move. This will avoid the unnecessary moving elements as in method 1.
function deleteItemsFromArray(array, delete_list) {
for (let i = array.length - 1; i > -1; i--) {
if (delete_list.includes(array[i])) {
array.copyWithin(i, i + 1).pop();
}
}
}
// Alternate way, with minimal copy/move group of elements.
function deleteItemsFromArrayAlternate(array, delete_list) {
let index = -1;
let count = 0;
for (let i = 0; i <= array.length; i++) {
if (delete_list.includes(array[i]) || !(i in array)) {
if (index > -1) {
array.copyWithin(index - count + 1, index + 1, i);
}
count += 1;
index = i;
}
}
array.length = array.length - delete_list.length;
}
const array = [9, 12, 3, 4, 5, 6, 7];
deleteItemsFromArray(array, [9, 6, 7]);
console.log(array);

How can I iterate & match the values from two different sized arrays until the longer array has been exhausted?

Say I have two arrays with the following values:
let array1 = (1,2,3,4);
let array2 = (1,2,3,4,5,6,7,8);
How do I exhaustively assign the values from array2 so that all of them are assigned to a key from array1; like so:
let result = (
1: {1,5},
2: {2,6},
3: {3,7},
4: {4,8},
);
If there were 9 values in array 2 then it would continue looping until:
let result = (
1: {1,5,9},
2: {2,6},
3: {3,7},
4: {4,8},
);
In my real-world example, array1 will be minutes, so {1..60}, array2 will be an unknown number of dates (more than 60). I want to continue assigning the unknown number of dates a key until all dates are assigned a minute key from 1-60.
Unless I misunderstand your question, one way to accomplish this is to implement array1 as a simple 2D array: an array of arrays.
let array1 = [[1],[2],[3],[4]];
let array2 = [1,2,3,4,5,6,7,8,9];
let row = 0;
let column = 0;
for (count = 0; count < array2.length; count++) {
if (row >= array1.length) {
row = 0;
column++;
}
array1[row][column] = array2[count];
row++;
}
consol.log(array1);
Try this quickly by going to the url "about:blank" and then right click somewhere and click inspect. Go to the console tab and paste the code above and press enter. Click the arrow from the output to expand the array and you should find that it worked as required. Also, not that it matters in your case, but this method of using the >= comparison instead of using % is faster for the task.
Try this:
let array1 = [1, 2, 3, 4];
let array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let result = [];
for(let i=0; i<array1.length; i++) {
result[i] = [];
for(let j=i; j<array2.length; j=j+array1.length) {
result[i].push(array2[j]);
}
}
console.log(result);

adding elements to the same array being iterated in js

I have a JavaScript array of length 3
arr = [1, 3, 8];
Is there a way to add elements to arr while I am iterating over it? I want to insert two values 10 and 20 into the existing arr. Can I do it like this? The newly added elements, 10 and 20, must also be looped over in the same for in loop.
for(var i in arr) {
if( i == 0 ) {
arr[length + 0] = 10;
arr[length + 1] = 20;
}
}
Or, what is the correct way to add elements to an array while iterating and making sure that the newly added elements will also be looped over?
You could use a for statement and check the length while iterating the array.
With for ... in statement, iteration of new elements is not granted.
Properties added to the object over which iteration is occurring may either be visited or omitted from iteration. In general it is best not to add, modify or remove properties from the object during iteration, other than the property currently being visited.
var array = [1, 3, 8],
i;
for (i = 0; i < array.length; i++) {
console.log(array[i]);
if (i === 0) {
array.push(10, 20);
}
}
You really shouldn't ever need to do this, there's probably a better method. But, if you absolutely have to, use a while loop instead:
var arr = [1, 2, 3];
var i = 0;
while (i < arr.length) {
if( i == 0 ) {
arr.push(10, 20);
}
console.log(arr[i]); // 1, 2, 3, 10, 20
i++;
}

Filtering arrays of complex objects with loops

I have two arrays of complex nexted objects that I'm looking for qualifying values within using loops and if statements as seen below. When I find a qualifying object, I need to filter that object out during the next go around of the loop. I'm trying to do that with an array as you can see here but it isn't working as the array starts over during each iteration of the loop. The following version is a simplified version of my code.
I want to update the values in array2 based on the if statement so that those values are not repeated in the nested loop. Instead my emptyArray remains empty instead of adding values from the array2 as elements of array2 are equal to elements of array.
To be clear, right now emptyArray remains empty and never filters array2. I'd like to see emptyArray collect value 2 at the start of the outer loop's second iteration then I'd like to see emptyArray collect value 4 at the start of the 4th iteration of the outer loop.
I'd want to filter each of these values from array2 as they become part of emptyArray so that they do not set off the if statement during the 6th and 8th iterations of the outer loop. I imagine that emptyArray = [2, 4] and array2 = [6, 8, 10] when the loops are finished.
Bottom line, I need emptyArray to collect the qualifying values and pass them back to var array2 for filtering as the loop processes. Remember this is a simplified version of the arrays, and underscore based solution would be very complicated for me to implement or for you to successfully suggest without much more detail.
My code:
var array = [1, 2, 3, 4, 1, 2, 3, 4];
var array2 = [2, 4, 6, 8, 10];
var emptyArray = [];
for (i = 0; i < array.length; i++){
var something = array[i];
var array2 = _.without(array2, emptyArray);
for (a = 0; a < array2.length; a++){
var value = array2[a];
if(something === value){
emptyArray.push(value);
break;
}
}
}
There are a few things wrong with your code, but the reason why you think that push isn't working is because you are overriding your array2 inside the loop.
The push never gets called because your for loop sees an empty array2 when you are doing var array2 = _.without(array2, emptyArray);
Basically var array2 = _.without(array2 /* this is empty, you just overrode it in this scope */, emptyArray); will always result in an empty array and your for loop will exit because length is array2.length === 0 from the start.
Also, you want to use _.difference instead of _.without
var array = [1, 2, 3, 4, 1, 2, 3, 4];
var array2 = [2, 4, 6, 8, 10];
var emptyArray = [];
for (var i = 0; i < array.length; i++) {
var something = array[i];
array2 = _.difference(array2, emptyArray);
for (var j = 0; j < array2.length; j++) {
var value = array2[j];
if (something === value) {
emptyArray.push(value);
break;
}
}
}
console.log("array2",array2);
console.log("emptyArray", emptyArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.js"></script>
array2 [6, 8, 10]
emptyArray [2, 4]
var array = [1, 2, 3, 4, 1, 2, 3, 4];
var array2 = [2, 4, 6, 8, 10];
var emptyArray = [];
for (var i = 0; i < array.length; i++) {
var something = array[i];
for (var j = 0; j < array2.length; j++) {
var value = array2[j];
if (something === value) {
array2 = _.without(array2, value);
break;
}
}
}

Categories

Resources