Swapping two items in a javascript array [duplicate] - javascript

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Javascript swap array elements
I have a array like this:
this.myArray = [0,1,2,3,4,5,6,7,8,9];
Now what I want to do is, swap positions of two items give their positions.
For example, i want to swap item 4 (which is 3) with item 8 (which is 7)
Which should result in:
this.myArray = [0,1,2,7,4,5,6,3,8,9];
How can I achieve this?

The return value from a splice is the element(s) that was removed-
no need of a temp variable
Array.prototype.swapItems = function(a, b){
this[a] = this.splice(b, 1, this[a])[0];
return this;
}
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
alert(arr.swapItems(3, 7));
returned value: (Array)
0,1,2,7,4,5,6,3,8,9

Just reassign the elements, creating an intermediate variable to save the first one you over-write:
var swapArrayElements = function(arr, indexA, indexB) {
var temp = arr[indexA];
arr[indexA] = arr[indexB];
arr[indexB] = temp;
};
// You would use this like: swapArrayElements(myArray, 3, 7);
If you want to make this easier to use, you can even add this to the builtin Array prototype (as kennebec# suggests); however, be aware that this is generally a bad pattern to avoid (since this can create issues when multiple different libraries have different ideas of what belongs in the builtin types):
Array.prototype.swap = function(indexA, indexB) {
swapArrayElements(this, indexA, indexB);
};
// You would use this like myArray.swap(3, 7);
Note that this solution is significantly more efficient than the alternative using splice(). (O(1) vs O(n)).

You can just use a temp variable to move things around, for example:
var temp = this.myArray[3];
this.myArray[3] = this.myArray[7];
this.myArray[7] = temp;
You can test it out here, or in function form:
Array.prototype.swap = function(a, b) {
var temp = this[a];
this[a] = this[b];
this[b] = temp;
};
Then you'd just call it like this:
this.myArray.swap(3, 7);
You can test that version here.

Related

Spinning the elements of an array clockwise in JS

I am supposed to rotate an array of integers clockwise in JS.
Here is my code for it:
function rotateArray(N, NArray)
{
//write your Logic here:
for(j=0;j<2;j++){
var temp=NArray[N-1];
for(i=0;i<N-1;i++){
NArray[i+1]=NArray[i];
}
NArray[0]=temp;
}
return NArray;
}
// INPUT [uncomment & modify if required]
var N = gets();
var NArray = new Array(N);
var temp = gets();
NArray = temp.split(' ').map(function(item) { return parseInt(item, 10);});
// OUTPUT [uncomment & modify if required]
console.log(rotateArray(N, NArray));
The code accepts an integer N which is the length of the array. The input is as follows:
4
1 2 3 4
The correct answer for this case is supposed to be
4 1 2 3
But my code returns
4 1 1 1
I cannot find where my code is going wrong. Please help me out.
All you need to do is move one item from the end of the array to the beginning. This is very simple to accomplish with .pop() (removes an item from the end of an array), then declare a new array with that element as the first:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem, ...NArray];
}
console.log(rotateArray(1, [1, 2, 3, 4]));
Doing anything else, like using nested loops, will make things more unnecessarily complicated (and buggy) than they need to be.
If you don't want to use spread syntax, you can use concat instead, to join the lastItem with the NArray:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem].concat(NArray);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
If you aren't allowed to use .pop, then look up the last element of the array by accessing the array's [length - 1] property, and take all elements before the last element with .slice (which creates a sub portion of the array from two indicies - here, from indicies 0 to the next-to-last element):
function rotateArray(N, NArray) {
const lastItem = NArray[NArray.length - 1];
const firstItems = NArray.slice(0, NArray.length - 1);
return [lastItem].concat(firstItems);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
function rotate(array,n){
Math.abs(n)>array.length?n=n%array.length:n;
if(n<0){
n=Math.abs(n)
return array.slice(n,array.length).concat(array.slice(0,n));
}else{
return array.slice(n-1,array.length).concat(array.slice(0,n-1));
}
}
console.log(rotate([1, 2, 3, 4, 5],-3));
The answer by #CertainPerformance is great but there's a simpler way to achieve this. Just combine pop with unshift.
let a = [1,2,3,4];
a?.length && a.unshift(a.pop());
console.log(a);
You need to check the length first so you don't end up with [undefined] if you start with an empty array.

JavaScript Array.concat and push workaround

It's always tricky to think Array.concat thing. Often, I just want to use mutable Array.push because I simply add extra-data on the immutable data. So, I usually do:
array[array.length] = newData;
I've asked a question related got some answers here: How to store data of a functional chain
const L = (a) => {
const m = a => (m.list ? m.list : m.list = [])
.push(a) && m;
//use `concat` and refactor needed instead of `push`
//that is not immutable
return m(a); // Object construction!
};
console.log(L);
console.log(L(2));
console.log(L(1)(2)(3))
some outputs:
{ [Function: m] list: [ 2 ] }
{ [Function: m] list: [ 1, 2, 3 ] }
I feel that push should be replaced with using concat, but still, push makes the code elegant simply because we don't want to prepare another object here.
Basically, I want to do:
arr1 = arr1.concat(arr2);
but, is there any way to write
arr1[arr1.length] = arr2;
which ends up with a nested array, and does not work.
You could assign a new array with a default array for not given m.list.
const L = (a) => {
const m = a => (m.list = (m.list || []).concat(a), m);
return m(a);
};
console.log(L.list);
console.log(L(2).list);
console.log(L(1)(2)(3).list);
You can use multiple parameters in Array.push so:
var a = [];
a.push(3, 4) // a is now [3, 4]
Combined with the ES6 spread syntax:
var a = [1, 2];
var b = [3, 4]
a.push(...b); // a is now [1, 2, 3, 4]
arr1[arr1.length] represents a single value, the value at index arr1.length.
Imagine this array
[ 1 , 2 , 3 , 4 ] // arr of length 4
^0 ^1 ^2 ^3 // indexes
If we say arr1[arr1.length] = someThing
We ask javascript to put something right here, and only here, at index 4:
[ 1 , 2 , 3 , 4 , ] // arr of length 4
^0 ^1 ^2 ^3 ^4 // add someThing in index 4
So, if we want to add something strictly with arr1[arr1.length], then we need to keep doing that for each index. for each meaning any kind of loop. E.G:
// Not recommended to use
var arr1 = [1,2,3];
var arr2 = [3,4,5];
while (arr2.length){
arr1[arr1.length] = arr2.shift();
}
console.log(arr1); // [1,2,3,3,4,5]
console.log(arr2); // []
But, as you can see, this method, or any similar one, even if optimized, is not the right approach. You need a concatenation.
Since you mention a functional one, which returns the resulting array, you can simply replace the initial array and make use of spread operator:
var arr1 = [1,2,3];
var arr2 = [3,4,5];
console.log(arr1 = [...arr1,...arr2]); // [1,2,3,3,4,5]

Duplicate an array an arbitrary number of times (javascript)

Let's say I'm given an array. The length of this array is 3, and has 3 elements:
var array = ['1','2','3'];
Eventually I will need to check if this array is equal to an array with the same elements, but just twice now. My new array is:
var newArray = ['1','2','3','1','2','3'];
I know I can use array.splice() to duplicate an array, but how can I duplicate it an unknown amount of times? Basically what I want is something that would have the effect of
var dupeArray = array*2;
const duplicateArr = (arr, times) =>
Array(times)
.fill([...arr])
.reduce((a, b) => a.concat(b));
This should work. It creates a new array with a size of how many times you want to duplicate it. It fills it with copies of the array. Then it uses reduce to join all the arrays into a single array.
The simplest solution is often the best one:
function replicate(arr, times) {
var al = arr.length,
rl = al*times,
res = new Array(rl);
for (var i=0; i<rl; i++)
res[i] = arr[i % al];
return res;
}
(or use nested loops such as #UsamaNorman).
However, if you want to be clever, you also can repeatedly concat the array to itself:
function replicate(arr, times) {
for (var parts = []; times > 0; times >>= 1) {
if (times & 1)
parts.push(arr);
arr = arr.concat(arr);
}
return Array.prototype.concat.apply([], parts);
}
Basic but worked for me.
var num = 2;
while(num>0){
array = array.concat(array);
num--}
Here's a fairly concise, non-recursive way of replicating an array an arbitrary number of times:
function replicateArray(array, n) {
// Create an array of size "n" with undefined values
var arrays = Array.apply(null, new Array(n));
// Replace each "undefined" with our array, resulting in an array of n copies of our array
arrays = arrays.map(function() { return array });
// Flatten our array of arrays
return [].concat.apply([], arrays);
}
console.log(replicateArray([1,2,3],4)); // output: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
What's going on?
The first two lines use apply and map to create an array of "n" copies of your array.
The last line uses apply to flatten our recently generated array of arrays.
Seriously though, what's going on?
If you haven't used apply or map, the code might be confusing.
The first piece of magic sauce here is the use of apply() which makes it possible to either pass an array to a function as though it were a parameter list.
Apply uses three pieces of information: x.apply(y,z)
x is the function being called
y is the object that the function is being called on (if null, it uses global)
z is the parameter list
Put in terms of code, it translates to: y.x(z[0], z[1], z[2],...)
For example
var arrays = Array.apply(null, new Array(n));
is the same as writing
var arrays = Array(undefined,undefined,undefined,... /*Repeat N Times*/);
The second piece of magic is the use of map() which calls a function for each element of an array and creates a list of return values.
This uses two pieces of information: x.map(y)
x is an array
y is a function to be invoked on each element of the array
For example
var returnArray = [1,2,3].map(function(x) {return x + 1;});
would create the array [2,3,4]
In our case we passed in a function which always returns a static value (the array we want to duplicate) which means the result of this map is a list of n copies of our array.
You can do:
var array = ['1','2','3'];
function nplicate(times, array){
//Times = 2, then concat 1 time to duplicate. Times = 3, then concat 2 times for duplicate. Etc.
times = times -1;
var result = array;
while(times > 0){
result = result.concat(array);
times--;
}
return result;
}
console.log(nplicate(2,array));
You concat the same array n times.
Use concat function and some logic: http://www.w3schools.com/jsref/jsref_concat_array.asp
Keep it short and sweet
function repeat(a, n, r) {
return !n ? r : repeat(a, --n, (r||[]).concat(a));
}
console.log(repeat([1,2,3], 4)); // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
http://jsfiddle.net/fLo3uubk/
if you are inside a loop you can verify the current loop index with the array length and then multiply it's content.
let arr = [1, 2, 3];
if(currentIndex > arr.length){
//if your using a loop, make sure to keep arr at a level that it won't reset each loop
arr.push(...arr);
}
Full Example:
https://jsfiddle.net/5k28yq0L/
I think you will have to write your own function, try this:
function dupArray(var n,var arr){
var newArr=[];
for(var j=0;j<n;j++)
for(var i=0;i<arr.length;i++){
newArr.push(arr[i]);
}
return newArr;
}
A rather crude solution for checking that it duplicates...
You could check for a variation of the length using modulus:
Then if it might be, loop over the contents and compare each value until done. If at any point it doesn't match before ending, then it either didn't repeat or stopped repeating before the end.
if (array2.length % array1.length == 0){
// It might be a dupe
for (var i in array2){
if (i != array1[array2.length % indexOf(i)]) { // Not Repeating }
}
}

Filling an array with an identical function [duplicate]

This question already has answers here:
Functional approach to basic array construction
(5 answers)
Closed 8 years ago.
I'm trying to create a function that returns an array with n elements, that are all the same function (this array will later be used to call those functions in parallel using async).
I can easily loop over an array and add the function to each element, but was wondering if I can do it in one line, using map:
//the function to point to
var double = function(x) {
return x*2;
};
//this function will create the array - just a filler for a one-liner
var createConsumersArray = function(numOfConsumers) {
var consumers = (new Array(2)).map(function(x){return double;});
return consumers;
};
var t = createConsumersArray(2);
console.log(t); //prints [,]
console.log(t[1](2)); //TypeError: Property '1' of object , is not a function
If I pre-fill the array with constants, the map works, i.e.:
var x = [1,2,3];
console.log(x.map(function(x){return double;})); //prints [ [Function], [Function], [Function] ]
console.log(x[1](2)); //prints 4
How can I accomplish filling an array with an identical function in the shortest way?
You have to change a little.
var createConsumersArray = function(numOfConsumers) {
var consumers = Array.apply(null, Array(numOfConsumers)).map(function(){return double;});
return consumers;
};
This is more functional programming. If you'd like to program in this style, I'd recommend you look at underscore.js. Here's an example of a range function:
_.range(10);
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
For your use case you would do:
_.map(_.range(4), function(num){ return double; });
Here's the corresponding jsfiddle example:

multiple arrays into one array

I need help with the five.myArraysCombined property.
I need it to equal just 1 array (which it currently does in fiddle) and I need it to NOT add any numbers together. (so each number in the array shouldn't be over 20, just like no number in the other arrays are over 20)
http://jsfiddle.net/Dc6HN/1/
For example, if the five arrays are like this
five.myArray1 = [7,2,9,19,3];
five.myArray2 = [6,18,8,1,7];
five.myArray3 = [7,19,4,8,2];
five.myArray4 = [11,9,1,14,5];
five.myArray5 = [3,18,8,9,2];
then the all those arrays combined should be like this
five.myArraysCombined = [7,2,9,19,3,6,18,8,1,7,7,19,4,8,2,11,9,1,14,5,3,18,8,9,2];
Relevant code :
function theNumberClass() {
this.myArray = [[],[],[],[],[]];
this.myArraysCombined = [];
}
var five = new theNumberClass();
function prePickNumbers(objName, theNum, theSumNum, theMaxNum, theMinNum) {
var zzz = [];
for (var x = 0; x < theNum; x += 1) {
pickNumbers(objName.myArray[x], theNum, theSumNum, theMaxNum, theMinNum);
zzz += objName.myArray[x];
}
objName.myArraysCombined.push(zzz);
}
prePickNumbers(five, 5, 40, 20, 1);
My latest attempt was with var zzz and then pushing it to the property, but when I do that it adds up the numbers in the array at times, which is not what I need.
I've also tried several attempts using the .concat(), but it seems to turn it into a string and sometimes also adds up the numbers.
Suppose you have those arrays :
var a = [1, 2, 3]
var b = [4, 5, 6]
var c = [8]
Then you can get a merge of all those with
var all = [].concat.apply([],[a,b,c])
or with
var all = [a,b,c].reduce(function(merged, arr){ return merged.concat(arr) })
In both cases you get
[1, 2, 3, 4, 5, 6, 8]
The first solution is simpler, the second one is more extensible if you want, for example, to remove duplicate or do any kind of filtering/transformation.
I would guess that the issue is the "+=" operator. This operator is used to sum values, not add new elements to an array. Take the following line of code as an example:
zzz += objName.myArray[x];
What I am guessing is that "myArray[x]" is getting added to the value of zzz instead of getting appended to the end of the array. When adding elements to an array in javascript, push is the best option. A better way to write this line is:
zzz.push(objName.myArray[x]);
The question was a bit confusing so I'm not sure if this is what you are looking for but hopefully it will help anyways.
five.reduce(function(o,n){return o.concat(n)},[])
This will reduce the array to a single value, in this case an array of numbers. You can look up Array.reduce() on MDN for more info.
After many hours trying all suggestions left on this thread and another one, and trying multiple other things. I think I finally found a very simple way to do this. And it's the only way I tried that works 100% like I want.
http://jsfiddle.net/Dc6HN/2/
function prePickNumbers(objName, theNum, theSumNum, theMaxNum, theMinNum) {
for (var x = 0; x < theNum; x += 1) {
pickNumbers(objName.myArray[x], theNum, theSumNum, theMaxNum, theMinNum);
objName.myArraysCombined.push(objName.myArray[x]);
}
objName.myArraysCombined = objName.myArraysCombined.toString();
objName.myArraysCombined = objName.myArraysCombined.split(',');
}

Categories

Resources