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]
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 am trying to use the splice method to add the values from the first array into the second array in the index location provided by the third parameter. I was confident that my solution would work, even verified that my understanding of slice was correct. However, when I log this in console it returns as an empty array.
I feel like I am really close, but something is missing.
function frankenSplice(arr1, arr2, n) {
//copies made as to not disrupt referece.
let array1 = arr1.slice(0, arr1.length);
let array2 = arr2.slice(0, arr2.length);
let mutatedArray = array2.splice(n,0,...array1);
return mutatedArray;}
frankenSplice([1, 2, 3], [4, 5], 1) should return [4, 1, 2, 3, 5].
Also, is this a good usage of creating copies of the arrays in the function? I'm learning about referencing non-primitives and if I'm not mistaken creating the copies in the scope of the function protects the original reference from being modified. It's not pointless in this context is it?
The problem is that the return value for splice is not the array that got mutated, but the removed elements, in an array:
Return value: An array containing the deleted elements. If only one element is removed, an array of one element is returned. If no elements are removed, an empty array is returned.
You aren't removing any elements with splice, so the result is an empty array. Don't assign the result of splice to a variable, and return array2 instead:
function frankenSplice(arr1, arr2, n) {
//copies made as to not disrupt referece.
let array1 = arr1.slice(0, arr1.length);
let array2 = arr2.slice(0, arr2.length);
array2.splice(n, 0, ...array1);
return array2;
}
console.log(frankenSplice([1, 2, 3], [4, 5], 1))
Also note that you can use slice() without any arguments to create a shallow copy of an array, no need for (0, arr.length):
function frankenSplice(arr1, arr2, n) {
//copies made as to not disrupt referece.
let array1 = arr1.slice();
let array2 = arr2.slice();
array2.splice(n, 0, ...array1);
return array2;
}
console.log(frankenSplice([1, 2, 3], [4, 5], 1))
Another option is to immediately return an array into which you spread sliced sections of the original arrays, which might be clearer than using splice:
function frankenSplice(arr1, arr2, n) {
return [
...arr2.slice(0, n),
...arr1,
...arr2.slice(n)
];
}
console.log(frankenSplice([1, 2, 3], [4, 5], 1))
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.
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);
is there any way to make javascript array to initialize all the values to 0 without iteration like as shown below
var array = [1, 2, 3, 4, 5];
to
[0, 0, 0, 0, 0]
You could, in compliant browsers, use Array.prototype.fill():
var array = [1, 2, 3, 4, 5];
array.fill(0); // [0, 0, 0, 0, 0]
References:
Array.prototype.fill().
Array.apply(null, new Array(5)).map(Number.prototype.valueOf, 0))
Useful article Initializing arrays
Its a bit tricky. But it works
var array = [1, 2, 3, 4, 5];
array = JSON.parse(JSON.stringify(array).replace(/(\d+)/g,0)); // Returns [0,0,0,0,0]
i guess you don't need eval if you use JSON.parse() to build the empties and splice() to mutate the existing array instead of just making a new array full of zeros:
var r=[1, 2, 3, 4, 5];
[].splice.apply(r,
[0, r.length].concat(
JSON.parse("[0"+new Array(r.length).join(",0")+"]")
));
alert(r); // shows: "0,0,0,0,0"
Answers based on map()/fill() will not affect the orig array as desired, but those solutions could use splice like the above answer to do so, the only difference then is how one build the zero-filled array.
EDIT: kudos to Gilsha, i was working on an eval-based answer when you reminded me that JSON would be enough.