I want to iterate over an array in reverse order using Lodash. Is that possible?
My code looks like below.
var array = [1, 2, 3, 4, 5];
_.each(array, function(i) {
_.remove(array, i);
});
When I do _.pullAt(array, 0) new array is [2, 3, 4, 5]. All array elements shifted to left by 1 position, and current index is pointing to element 3. After next iteration, 3 will get deleted and then 5. After 3rd iteration array contains [2, 4] which I couldn't delete.
If I iterate over the array in reverse order, then this problem won't arise. In Lodash, can I iterate over an array in reverse order?
You can use _.reverse available in version 4:
var array = [1, 2, 3, 4, 5];
array = _.reverse(array)
console.log(array)
//5, 4, 3, 2, 1
See How do I empty an array in JavaScript? if you only want that and choose your weapon.
Otherwise, strictly answering the question, to iterate the indices from the length of the array to zero, you could use the "down-to" --> operator1. But that's not really necessary, even underscore isn't necessary in this case as the .pop function is enough.
var arr = [1, 2, 3, 4, 5],
index = arr.length;
while (index --> 0) {
console.log(index);
arr.pop();
}
console.log(arr);
If you're using Lodash like the functions referenced in the question seem to indicate, you could use _.eachRight.
var arr = [1, 2, 3, 4, 5];
_.eachRight(arr, function(value) {
console.log(value);
arr.pop();
});
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
1 The down-to operator doesn't exist and is only a -- decrement followed by a > comparison.
Related
This is my first question on stackoverflow, I am new :) learning JS. I have a question. I wrote this function:
function inverseSlice(items, a, b) {
return items.splice(a, b);
}
inverseSlice([1, 2, 3, 4, 5, 6], 2, 4)
(4) [3, 4, 5, 6]
Why this function returns last 4 digits, when according to docs on MDN (which I read 10 times already :P) splice() method should remove here only 2 middle ones (3, 4)? It should return [1, 2, 5, 6]. Am I right? Thank You for all Your help :)
It's doing exactly what it advertises, it "returns an array containing the deleted elements."
function inverseSlice(items, a, b) {
return items.splice(a, b);
}
let array = [1, 2, 3, 4, 5, 6, 7, 8];
// Deletes 4 entries starting at index 2,
// or in other words [3,4,5,6] are snipped
inverseSlice(array, 2, 4);
console.log(array);
Unless you keep a reference to the array you're passing in you'll never observe anything about how it ends up, you'll only get the deleted elements.
splice will
Mutate the original array: remove N items, where N is the third parameter, starting from the start index (first parameter) to the number specified (so here, it'll remove indicies 2 through 5 from the array; indicies 2, 3, 4, and 5, a total of 4 get removed)
Return the removed elements - so, here, that's [3, 4, 5, 6].
The original array is now [1, 2], but you're logging what was returned by .splice, not the original array.
If you wanted [1, 2, 5, 6], you'd want to specify 2 for the 3rd argument (2 items to remove), and then log the original array:
function inverseSlice(items, a, b) {
return items.splice(a, b);
}
const arr = [1, 2, 3, 4, 5, 6];
const removedItems = inverseSlice(arr, 2, 2);
console.log(arr);
console.log(removedItems);
What you are confused about is the arguments to splice, The two arguments that you pass to splice are not the start and end index but the start index and the count of items to be deleted.
Hence in your example it deleted items from 2 to 5 index and returned you the resultant array i.e [3, 4, 5, 6]
As per the docs:
Syntax:
let arrDeletedItems = arr.splice(start[, deleteCount[, item1[, item2[, ...]]]])
Parameters
Start : The index at which to start changing the array.
deleteCount: n integer indicating the number of elements in the array to remove from start.
item1, item2, ... : The elements to add to the array, beginning from start. If you do not specify any elements, splice() will only remove
elements from the array.
I'm trying to populate an array with all values retrieved (I am in a loop) and then to delete values already present in the yearsJustSelected array:
yearsJustSelected.forEach((el:any)=>{
yearsJustSelectedAll.push(el);
});
yearsJustSelectedFiltered = yearsJustSelected.filter((el: any) => !yearsJustSelectedAll.includes(el));
For example:
loop 1 --> yearsJustSelected=[1, 2, 3] - yearsJustSelectedAll=[1, 2, 3] - yearsJustSelectedFiltered = []
loop 2 --> yearsJustSelected=[2, 3, 4, 5] - yearsJustSelectedAll=[1, 2, 3, 4, 5] - yearsJustSelectedFiltered=[4, 5] --> because [2, 3 ] were already present in the yearsJustSelectedAll in the first loop
This code:
yearsJustSelectedFiltered = yearsJustSelected.filter((el: any) => !yearsJustSelectedAll.includes(el));
always return an empty array.
yearsJustSelected.forEach((el:any)=>{
yearsJustSelectedAll.push(el);
});
// The code above will add all elements in yearsJustSelected into yearsJustSelectedAll
// making the two arrays the same.
There are no instances where one array has elements that are not in the other array
You could check if the target array does not have the item. Then push the item to the target array.
function select(source, target) {
source.forEach(v => target.includes(v) || target.push(v));
}
var yearsJustSelectedAll = [];
select([1, 2, 3], yearsJustSelectedAll);
console.log(...yearsJustSelectedAll);
select([2, 3, 4, 5], yearsJustSelectedAll);
console.log(...yearsJustSelectedAll);
select([4, 5], yearsJustSelectedAll);
console.log(...yearsJustSelectedAll);
I found many posts on stack overflow about that similar subject but none of them solve this issue here.
<script>
//Array GanginaA contains duplicated values.
//Array GanginaB contains only unique values that have been fetched from GanginaA
GanginaA=[0,1,2,3,4,5,5,6,7,8,9,9];
GanginaB=[0,1,2,3,4,5,6,7,8,9];
var hezi=<!--The Magic Goes Here-->
console.log(hezi);
/*
* Expected Output:
* 5,9
*/
</script>
GanginaA will always be longer or identical to GanginaB so there is no reason to calculate by the value of the longer array length.
GanginaB will always contains unique values that taken from GanginaA so it will always be the shorter array length or identical to GanginaA array.
Now it makes it a lot easier to find doubles.
You can use filter to get the elements like below
GanginaA = [0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9];
GanginaB = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var hezi = GanginaB.filter(function (item, index) {
return GanginaA.indexOf(item) !== GanginaA.lastIndexOf(item)
});
console.log(hezi.join(" , ")); // 5, 9
the easier I can think of :
var hezi=[];
for (var i=0;i<GanginaA.length;i++){
hezi[GanginaA[i]] = GanginaA[i];
hezi[GanginaB[i]] = GanginaB[i];
}
hezi = hezi.filter (function(el){return el!=undefined;});
does everything in O(n) actions and not O(n^2)
Javascript's objects have hashmap like behaviour, so you can use them kind of like a set. If you iterate over all the values and set them to be keys within an object, you can use the Object.keys method to get an array of unique values out.
function uniqueValues() {
var unique = {};
[].forEach.call(arguments, function(array) {
array.forEach(function(value) {
unique[value] = true;
});
});
return Object.keys(unique);
};
This function will return the unique elements in any number of arrays, passed as arguments.
uniqueValues([1, 2, 3], [ 1, 1, 1], [2, 2, 2], [3, 3, 3]); // [ 1, 2 3 ]
One drawback to this method is that Javascript coerces all keys to strings, you can turn them back into numbers by changing the return statement to:
return Object.keys(unique).map(Number);
How do you efficiently scroll an array with looping either acting on the array itself or returning a new array
arr = [1,2,3,4,5]
i want to do something like this:
arr.scroll(-2)
arr now is [4,5,1,2,3]
Use Array.slice:
> arr.slice(-2).concat(arr.slice(0, -2));
[4, 5, 1, 2, 3]
You can then generalize it and extend Array.prototype with the scroll function:
Array.prototype.scroll = function (shift) {
return this.slice(shift).concat(this.slice(0, shift));
};
> arr.scroll(-2);
[4, 5, 1, 2, 3]
I have a numeric javascript array, that contains several objects with geodata in it.
What I need to do is, to add a dynamic count of new objects after a specific object in this array.
I know, that there is the splice function, but i do not know, how to make the count of new objects variable.
myArray.splice( pos, 0, ... );
What am I getting wrong?
Hope I understood what you meant.
var
oldA = [1, 2, 3],
newA = [4, 5];
oldA.splice.apply(oldA, (function (index, howMany, elements) {
// this is actually building the arguments array (2nd parameter)
// for the oldA.splice call
elements = elements.slice();
elements.splice(0, 0, index, howMany);
return elements;
}(/*index to insert at*/ 2, /*howMany to remove*/ 0, /*elements to insert*/ newA)));
console.log(oldA, newA); // [1, 2, 4, 5, 3] [4, 5]