How to double array values - javascript

I have an array:
arr = ["a", "b", c"]
I want to double values like
arr = ["a", "b", c", "a", "b", "c"]
(not in particular order).
What's the best way to do it in JavaScript?

Possible solution, using Array#concat.
var arr = ["a", "b", "c"],
res = arr.concat(arr);
console.log(res);

You could also use ES6 spread syntax with Array.push:
let arr = ['a', 'b', 'c'];
arr.push(...arr);
console.log(arr);

You can use Array() constructor and inside specify number of times you want to repeat array and then use fill() and spread syntax to create one array.
var arr = ["a", "b", "c"];
var newArr = [].concat(...Array(3).fill(arr))
console.log(newArr)

A for-loop solution which mutates the array itself.
var arr=["a","b","c"];
var len=arr.length;
for(var i=len;i<2*len;i++) arr[i]=arr[i-len]
console.log(arr);

Related

How to remove elements from array which are exist in second array in javascript? [duplicate]

This question already has answers here:
How to filter an array from all elements of another array
(24 answers)
Closed 2 years ago.
const arr1 = ["a", "b", "c", "d", "e"];
const arr2 = ["b", "d"];
I need to do something which remove "b" and "d" from arr1. Of course I need to remove elements from arr1 which exist in arr2 too.
Try using filter + includes:
const arr1 = ["a", "b", "c", "d", "e"];
const arr2 = ["b", "d"];
let result = arr1.filter(el => !arr2.includes(el));
console.log(result);

Array.concat reflects the change in resulting array when input nested array is modified after concatination

According to MDN, the description for concat is as below,
The concat() method is used to merge two or more arrays. This method
does not change the existing arrays, but instead returns a new array.
Consider the below code,
Example 1
const array1 = [['a'], 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2); // concatinate array1 and array2 and returns new array3.
console.log(array3);
array1.push('pushed'); // pushed as the last element to the array1
console.log(array3); // no change in array 3, looks correct
output
[["a"], "b", "c", "d", "e", "f"]
[["a"], "b", "c", "d", "e", "f"]
Example 2:
const array1 = [['a'], 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2); // concatinate array1 and array2 and returns new array3.
console.log(array3);
array1[0].push('pushed'); // pushed as the last element to the nested array at position 0
console.log(array3); // array 3 also changed, why?
output
[["a"], "b", "c", "d", "e", "f"]
[["a", "pushed"], "b", "c", "d", "e", "f"]
In the example 2, why did the content of array3 got changed even though the concatenation happened before the push of new element in array1.
NOTE: the only difference between the 2 examples is
Example1: array1.push('pushed')
Example2: array1[0].push('pushed')
I understand about pass by value and pass by reference (and arrays and objects share reference), but the thing which confused me is why is the nested array sharing reference and the original array was copied.
The element at index 0 in array1 (a non primitive) was copied by reference in the new array returned by array1.concat(array2) and stored in array3.
.push() mutates the array in place. When you mutate array1, it does not affect array3 because they do not share the same reference (concat returned a new array).
But because the element at index 0 in array1 (a non primitive) is sharing the same reference as the element at index 0 in array3 (which you can check by seeing that array1[0] === array3[0]; // true), mutating that array in array1 is mutating the same array in array3.
TLDR: array1 !== array3 but array1[0] === array3[0]
I understand about pass by value and pass by reference (and array and objects share reference), but the thing which confused me is why is the nested array sharing reference and the original array was copied.
That's how Array.concat works, it returns copies of the same elements in a new array.
You can do the same thing using Spread syntax:
const array3 = [...array1, ...array2];
We have copies of the same elements from array1 and array2 but in a new array [], so if an element is an array or an object it'll be copied by reference
Look at this example:
const array1 = [['a'], 'b', 'c'];
const array3 = array1.concat();
console.log('array3:', array3);
console.log('array3 === array1 ? :', array3 === array1);
console.log('array3[0] === array1[0] ? :', array3[0] === array1[0]);
The same example using Spread syntax:
const array1 = [['a'], 'b', 'c'];
const array3 = [...array1];
console.log('array3:', array3);
console.log('array3 === array1 ? :', array3 === array1);
console.log('array3[0] === array1[0] ? :', array3[0] === array1[0]);
Apart from those good answers posted above, Here is an interesting and a well explained article about deep and shallow copy.
how-to-differentiate-between-deep-and-shallow-copies by Lukas Gisder-Dubé

How can I assign keys to existing values in a JavaScript array

I recovered an array with values from a previous method and I need to go through it and assign each of the values a key in alphabetical order.
["T", "C", "α", "T(linked)", "C"]
This is my array, previously mentioned. I want to know how, when crossing the array will I be able to assign it a key of alphabetical form, so that the final result was:
["A:T", "B:C", "C:α", "D:T(linked), "E:C"]
Any advice will be welcome. Thank you in advance.
You can achieve it by using Array.prototype.map function.
let a = ["T", "C", "α", "T(linked)", "C"];
a = a.map((val,index)=>{ return `${String.fromCharCode(65 + index )}:${val}`; } ) ;
console.log(a);
By having single elements, you could just map the values with a prefix.
var data = ["T", "C", "α", "T(linked)", "C"],
result = data.map((v, i) => `${(i + 10).toString(36).toUpperCase()}:${v}`);
console.log(result);
In your input array:
["T, C", "α", "T(linked), C"]
are "T, C" and "T(linked), C" supposed to be elements as is, or are you missing quotation marks? In other words, did you mean this?
["T", "C", "α", "T(linked)", "C"]
You can use the map function. Using the code
newArray = array.map((value, index) => ...)
will generate a new array with a function done for each value and index of the old array.
array = ["T", "C", "α", "T(linked)", "C"];
newArray = array.map((value, index) => `${String.fromCharCode(index + 65)}:${value}`);
newArray will be set to
["A:T", "B:C", "C:α", "D:T(linked)", "E:C"]
If you don't understand that method of concatenating strings, use this instead.
array = ["T", "C", "α", "T(linked)", "C"];
newArray = array.map((value, index) => String.fromCharCode(index + 65) + ":" + value);

How to use _.pull() with regular expressions in Lodash?

I want to remove elements from an array when they match a certain regular expression.
Here is the Lodash documentation on the pull() method.
I want a result similar to this.
const array = ['a', 'b', 'c', 'a', 'b', 'c'];
 
_.pull(array, 'b', 'c',);
console.log(array); // [ 'a', 'a', ]
Only, I want to use regex instead of strings. But this does not achieve that result.
const array = ['a', 'b', 'c', 'a', 'b', 'c'];
const re = /(b|c)/gm
 
_.pull(array, re,);
console.log(array); // ["a", "b", "c", "a", "b", "c"]
What am I doing wrong?
The _.pull() method doesn't accept a predicate, use _.remove():
Removes all elements from array that predicate returns truthy for
const array = ['a', 'b', 'c', 'a', 'b', 'c'];
const re = /b|c/
_.remove(array, c => re.test(c));
console.log(array); // ["a", "a"]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
If you're interested in a vanilla JS solution, see below for using RegExp test!
let array = ['a', 'b', 'c', 'a', 'b', 'c'];
const re = /(b|c)/
array = array.filter(el => !re.test(el));
console.log(array);

JavaScript .push() inside function is overriding global variable

I have the following problem with .push() method:
var myArray = ["a", "b", "c", "d"];
function add(arr) {
arr.push("e");
return arr;
}
add(myArray);
// myArray is now ["a", "b", "c", "d", "e"]
Why it overrides myArray? Can't understand that...
Arrays in Javascript (and most other languages) are passed by reference.
When you write add(myArray), you are passing a reference to the same Array instance that the global myArray variable refers to.
Any changes to the array object will be visible through both references.
To copy the actual array instance, write add(myArray.slice());.
Note that this will not copy the objects inside of it.
If you need to be able to nest arrays, then I'd change the .add() function to have the .concat() duplicate the Array into a variable, .push() the new value into the new Array, and return it.
function add(arr) {
var newArr = arr.concat(); // duplicate
newArr.push("e"); // push new value
return newArr; // return new (modified) Array
}
You could use concat() as well, and return the new array it creates.
var myArray = ["a", "b", "c", "d"];
function add(arr) {
return arr.concat("e");
}
var newArray = add(myArray);
console.log( newArray ); // ["a", "b", "c", "d", "e"]
console.log( myArray ); // ["a", "b", "c", "d"]
So instead of two methods .slice() then .push(), you accomplish it with one .concat().
This also gives you the benefit of passing another Array instead of a string, so:
return arr.concat(["e","f"]);
would give you:
// ["a", "b", "c", "d", "e", "f"]
instead of:
// ["a", "b", "c", "d", ["e", "f"] ]

Categories