I am learning Javascript on a book and have to practice reversing an array by creating my own reverse function. The array must be reversed without creating a new variable to hold the reversed array. I thought I found a solution, but when I try to output my answer in 2 different ways (see below), I get different outputs:
function reverseArrayInPlace(array) {
for (var i = 0; i < array.length; i += 1) {
array = array.slice(0, i).concat(array.pop()).concat(array.slice(i));
}
console.log(array);
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
Here are the outputs:
reverseArrayInPlace(array);
console.log(array);
> [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
> [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
When console.log() is used within the function, I get my desired answer.
When console.log() is used outside the function, I get the original array with the last element missing. I would like an explanation to this phenomenon.
The array in the function is on a different scope than that at the global / window level -- the global array is never touched; the function changes a local copy of it instead.
If you didn't pass array as a parameter to the function, then it would act on the now unmasked global array variable:
function reverseArrayInPlace() { // <-- no parameter
for (var i = 0; i < array.length; i += 1) {
array = array.slice(0, i).concat(array.pop()).concat(array.slice(i));
}
console.log(array);
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
reverseArrayInPlace();
console.log(array);
(...although it is generally bad practice to use globals like that, partly because it's easy to accidentally mask them with local variables just as you did here. A better pattern would be for functions to receive their data as params and return a value, so you can decide, when you call the function, what to assign that returned value to.)
Inside reverseArrayInPlace you are reassigning the array variable, not changing (mutating) it. The array you pass in, therefore, is not changed. The inside console.log sees the new array while the one outside sees the original.
Perhaps you want something like this instead
function reverseArrayInPlace(array) {
for (var i = 0; i < array.length; i += 1) {
array = array.slice(0, i).concat(array.pop()).concat(array.slice(i));
}
return array;
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var newArray = reverseArrayInPlace(array)
console.log(newArray)
Just a different approach by using the function stack for storing an item of the array by popping the value, check the length of the array and call the function again with the same object reference and then unshift the temporary stored value.
While working for a small amount of values and because of the limited stack, it is not advisable to use this beside of educational purpose.
function reverseArrayInPlace(array) {
var temp = array.pop();
if (array.length) {
reverseArrayInPlace(array);
}
array.unshift(temp);
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
reverseArrayInPlace(array);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In the first loop of your for you are calling array.pop() which modifies the array passed as argument, but then you are creating a new array storing it in the same variable, so the reference to the original array is lost, and then in the subsequent loops the modified array is the one being generated inside your function.
Look at this code, I added a line to copy the original array, thus not modificating the original passed as argument.
function reverseArrayInPlace(array) {
array = array.slice(); //copying the passed array to not change the original
for (var i = 0; i < array.length; i += 1) {
array = array.slice(0, i).concat(array.pop()).concat(array.slice(i));
}
console.log(array);
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
reverseArrayInPlace(array);
console.log(array);
Related
I have a very simple array like this:
array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
I need to be able to remove a value, but I need to remove only one value if there's duplicate values. So if I remove the value 6, the array should become:
array = [1, 1, 7, 9, 6, 4, 5, 4];
The order of which one gets removed doesn't matter, so it could be the last no. 6 or the first no. 6. How can I do this?
Edit
I see there's a lot of confusion about why I need this, which results in incorrect answers. I'm making a Sudoku game and when a user inserts a number in a cell, the game has to check if the chosen number already occupies space in the same row or column. If so, the number of that specific row/column is added to this array. However, when a user fixes a mistake, the number of the row/column should be removed. A user can, however, make multiple mistakes in the same row or column, which is why I need to retain the duplicates in the array. Otherwise, users can make multiple mistakes in a row/column, and only fix one, and then the code will think there are no errors whatsoever anymore.
Hope this makes things more clear.
Try to get the index of your item with indexOf() and then call splice()
let array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
let index = array.indexOf(6);
array.splice(index,1);
console.log(array);
var array=[1, 1, 6, 7, 9, 6, 4, 5, 4],
removeFirst=function(val,array){
array.splice(array.indexOf(val),1)
return array;
};
console.log(removeFirst(6,array));
You can use Array.prototype.findIndex to find the first index at which the element to be removed appears and then splice it.
Also you can create a hastable to ascertain that we remove only if a duplicate is availabe - see demo below:
var array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
var hash = array.reduce(function(p,c){
p[c] = (p[c] || 0) + 1;
return p;
},{});
function remove(el) {
if(hash[el] < 2)
return;
array.splice(array.findIndex(function(e) {
return e == el;
}), 1);
}
remove(6);
remove(7);
console.log(array);
If order of removed element (not elements!) isn't important, you can use something like this:
array = [1, 1, 6, 7, 9, 6, 4, 5, 4];
function remove_if_dupe(elem, array) {
dupes=[];
for(i=0;i<array.length;i++) {
if(array[i] === elem) {
dupes.push(elem);
}
}
if(dupes.length>1) {
//is duplicated
array.splice(array.indexOf(elem), 1);
}
return array;
}
console.log(remove_if_dupe(6,array));
This should keep unique elements, hopefully.
I saw this function , though it works fine but I am bit puzzled about the function expressions. Here is the code
mapForEach(arr, fn) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
newArr.push(fn(arr[i]))
}
return newArr;
}
can anybody explain to nme what this rather complicated code is actually doing?
Lets say you have var array = [1, 2, 3, 5]; and then run var array2 = mapForEach(array, function(i) { return i * 2; })
array2 would then contain [2, 4, 6, 10].
So it returns a new array where you have the ability to modify each record with a function
mapForEach enumerates an array and calls a supplied function on each element.
example:
var a = [1, 2, 3];
console.log(mapForEach(a, (x) => x * 2));
would create a new array with the values (and output to console):
[2, 4, 6]
Basically it is an implementation of javascript native array function map, which creates a new array with the results of calling a provided function on every element in this array.
More info about mentioned function you can find here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 6 years ago.
Below is my array if items that I want to reduce it to a single list of arrays..
var input=[
[
2
],
[
3,
13
],
[
4,
14
],
[
5,
15,
25,
35
]
]
var output=[
2,
3,
13,
4,
14,
5,
15,
25,
35
]
My code:
function reduceArray(item){
for(var i=0;i<item.length;i++){
return i;
}
}
var result=result.map((item)=>{
if(item.length>0){
return reduceArray(item);
}else{
return item;
}
})
which produces the same result.Can anyone please figure out where I'm doing wrong or any other approach to achieve this..Thanks
input.reduce(function(a, x) { return a.concat(x); });
// => [2, 3, 13, 4, 14, 5, 15, 25, 35]
reduce sets the accumulator to the first element (or a starting value if provided), then calls the function with the accumulator and each successive element. The function we provide is concatenation. If we say input is [a, b, c], then the above command will be equivalent to a.concat(b).concat(c). [concat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) produces a new array by smushing two or more arrays together.
EDIT: Actually, there is another possible answer:
Array.prototype.concat.apply(input[0], array.slice(1));
// => [2, 3, 13, 4, 14, 5, 15, 25, 35]
This directly calls concat with multiple arguments; if input is again [a, b, c], then this is equivalent to a.concat(b, c). apply calls a function with a given receiver and arguments; slice will give us just a part of the array, in this case everything starting from the first element (which we need to chop off since it needs to be the receiver of the concat call).
One liner would be
input = [[2],[3,13],[4,14],[5,15,25,35]];
[].concat.apply([],input);
You can use lodash's flattenDeep()
_.flattenDeep([1, [2, [3, [4]], 5]]);
// → [1, 2, 3, 4, 5]
User concat.check this for more information http://www.w3schools.com/jsref/jsref_concat_array.asp
var input=[[2],[3,13],[4,14],[5,15,25,35]];
var output=[];
for(var i = 0; i < input.length; i++)
{
output = output.concat(input[i]);
}
console.log(output);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
use concat is the perfect way
The concat() method is used to join two or more arrays.
This method does not change the existing arrays, but returns a new array, containing the values of the joined arrays.
var newArr = [];
for(var i = 0; i < input.length; i++)
{
newArr = newArr.concat(input[i]);
}
console.log(newArr);
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);
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]