Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Let's say I have an array called array1:
var array1 = [1, 2, 5];
And I have another called array2:
var array2 = [3, 4];
I want to output the result [1, 2, 3, 4, 5] by inserting array2 at index number 2 of array1.
How can achieve this in JavaScript?
EDIT:
More things to note:
Array mutation in place does not matter, either way would be fine.
The order of the array elements does not matter, the task at hand is to merge two arrays at a specified index.
I've come up with one possible implementation:
// merge 'b' with 'a' at index 'i'
function merge(a, b, i=0) {
return a.slice(0, i).concat(b, a.slice(i));
}
var result = merge([1, 2, 5], [3, 4], 2);
console.log(result);
You might try spreading b's elements into splice, which adds a series of arguments at index i (the optional argument removal is ignored with 0). a will be modified in place.
const mergeInPlace = (a, b, i=0) => a.splice(i, 0, ...b);
const a = [1, 2, 5];
const b = [3, 4];
mergeInPlace(a, b, 2);
console.log(a);
If you want to avoid mutation, spread and slice is probably easiest:
const merge = (a, b, i=0) => [...a.slice(0, i), ...b, ...a.slice(i)];
const a = [1, 2, 5];
const b = [3, 4];
console.log(merge(a, b, 2));
If you don't want to mutate the original array you can spread slices out into a new array:
var array1 = [1, 2, 5];
var array2 = [3, 4];
function merge(a1, a2, i){
return [...a1.slice(0,i), ...a2, ...a1.slice(i)]
}
console.log(merge(array1, array2, 2))
// negative indexing too
console.log(merge(array1, array2, -2))
If the goal is just to order them:
array1.concat(array2).sort();
var array1 = [1, 2, 5],
array2 = [3, 4];
let r = array1.concat(array2).sort();
console.log(r);
If the goal is to insert at a certain index:
array1.splice(2,0,array2);
array1.flat();
var array1 = [1, 2, 5],
array2 = [3, 4];
array1.splice(2,0,array2);
let r = array1.flat();
console.log(r);
As an alternative to that you can use a functional approach. I offer this because I find .splice to be an ugly method that mutates the array,is too closely named to slice, and doesn't even return the array you're probably looking for.
let combineAt = (n, a, b) =>
a.reduce((ac, cv, ci) =>
(n === ci) ?
(ac.push(b, cv), ac.flat()) :
(ac.push(cv), ac), []);
combineAt(2,array1,array2);
var array1 = [1, 2, 5],
array2 = [3, 4];
let combineAt = (n, a, b) => a.reduce((ac, cv, ci) => (n === ci) ? (ac.push(b, cv), ac.flat()) : (ac.push(cv), ac), []);
let r = combineAt(2, array1, array2);
console.log(r);
I'm new in JS, can't find solution to do something like that
var arr = [0];
var elem = [1, 2, 3];
???
console.log(arr); // shows [0, [1, 2, 3]];
I've tried with .push(elem), JS decides that I passed array of values (not a single one), and concatenate content of arr and elem arrays, so that the result is [0, 1, 2, 3]
Use concat!
var arr = [0];
var elem = [1, 2, 3];
var newArr = arr.concat([elem]);
console.log(newArr); // => [0,[1,2,3]]
You may try to use spread operator to concatenate values of an array.
For example:
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5];
console.log(arr2);
//Output: [ 1, 2, 3, 4, 5 ]
Now, after you wrote, what you want,
[0, [1, 2, 3]]
you could use at lease three different approaches:
Simple assignment at the end of the array
var arr = [0],
elem = [1, 2, 3];
arr[arr.length] = elem;
console.log(arr);
Array#push for pushing a value/object at the end of an array, which is basically the same as above without indicating the place for inserting, but you can use more item for pusing to the array.
var arr = [0],
elem = [1, 2, 3];
arr.push(elem);
console.log(arr);
Array#concat, creating a new array with with the given array and the parameters. Here cou need to wrap the content in an array, because concat concatinates arrays.
var arr = [0],
elem = [1, 2, 3];
arr = arr.concat([elem]);
console.log(arr);
We all know you can do:
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arr3 = [...arr1, ...arr2]; // [1,2,3,3,4,5]
But how do you make this dynamic to concat N arrays?
One option is to use reduce:
let arrs = [[1, 2], [3, 4], [5, 6]];
arrs.reduce((a, b) => [...a, ...b], []);
Of course, this is a slow solution (quadratic time). Alternatively, if you can use Lodash, _.flatten does exactly what you want, and does it more efficiently (linear time).
EDIT
Or, adapted from Xotic750's comment below,
[].concat(...arrs);
Which should be efficient (linear time).
Another option could be:
const nArrays = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9],
[10, 11]
];
const flattened = [].concat(...nArrays);
console.log(flattened)
let fruits = ["apples", "bananas", "pears"];
let vegetables = ["corn", "potatoes", "carrots"];
let produce = [...fruits, ...vegetables];
console.log(produce);
Best option is to use FlatMap, which helps us to conact multiple arrays into one single array.
Example:
let arrs = [[1, 2], [3, 4], [5, 6]];
arrs.flatMap(a => a);
result will be
> (6) [1, 2, 3, 4, 5, 6]
Happy Coding...
Following solution works for me (spread operator in ES6):
let array = ['my','solution','works'];
let newArray = [];
let newArray2 = [];
newArray.push(...array); //adding to same array
newArray2.push([...array]); //adding as child/leaf/sub-array
console.log(newArray);
console.log(newArray2);
You can't do that with spread syntax alone, as spread syntax requires you to know how many arrays you are concatenating in advance. However, you could write the following function:
function concatN(...arguments) {
let accumulator = [];
for(let arg = 0; arg < arguments.length; arg = arg + 1) {
accumulator = [...accumulator, ...arguments[arg]];
}
return accumulator;
}
It probably won't be very efficient, though (repeated use of spread syntax is O(n²)). Using Array.prototype.concatwould be better. You can just do:
[].concat(all, of, your, arrays);
You can use spread element within for..of loop to concatenate array values to a single array
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arr3 = [];
for (let arr of [arr1, arr2 /* , arrN */]) arr3.push(...arr);
console.log(arr3);
You could use a recursive function and Array.prototype.concat
const concatN = (x,...xs) =>
x === undefined ? [] : x.concat(concatN(...xs))
console.log(concatN([1,2,3], [4,5,6], [7,8,9]))
// [1,2,3,4,5,6,7,8,9]
You can do the same thing using reduce and Array.prototype.concat. This is similar to the accepted answer but doesn't senselessly use spread syntax where x.concat(y) is perfectly acceptable (and likely heaps faster) in this case
const concatN = (...xs) =>
xs.reduce((x,y) => x.concat(y), [])
console.log(concatN([1,2,3], [4,5,6], [7,8,9]))
// [1,2,3,4,5,6,7,8,9]
We can resolve using es6 following way
function mergeTwo(arr1, arr2) {
let result = [...arr1, ...arr2];
return result.sort((a,b) => a-b);
}
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arrs = [arr1, arr2].flat(); // [1,2,3,3,4,5]
console.log(arrs);
How do I change a JS array in place (like a Ruby "dangerous" method, e.g. with trailing !)
Example:
If I have this:
var arr = [1, 2, 3]
How can I make this:
arr === [2, 4, 6]
(assuming I have an appropriate function for doubling numbers) in one step, without making any more variables?
Use Array.prototype.forEach() , third parameter is this : input array
var arr = [1, 2, 3];
arr.forEach(function(el, index, array) {
array[index] = el * 2
});
console.log(arr)
A smart Array.prototype.map() and an assignment will do.
The map() method creates a new array with the results of calling a provided function on every element in this array.
var arr = [1, 2, 3];
arr = arr.map(function (a) {
return 2 * a;
});
document.write('<pre>' + JSON.stringify(arr, 0, 4) + '</pre>');
map() returns a new array, but it can also modify the array in-place if the callback function works on the array's elements:
function double(el, i, array) {
array[i]= el * 2;
} //double
var arr= [1, 2, 3];
arr.map(double);
console.log(arr); // [2, 4, 6]
var Arr1 = [1,3,4,5,6];
var Arr2 = [4,5,6,8,9,10];
I am trying to do merge these two arrays and output coming is [1,3,4,5,6,4,5,6]
I have used $.merge(Arr1, Arr2); this piece to merge them. Using alert I can see the merged array like above.
Now my question is how can I get the following output:
[1,3,4,5,6,8,9,10]
i.e. the elements should be unique as well as sorted in the same manner I have mentioned.
Please help.
You can use Array.prototype.sort() to do a real numeric sort and use Array.prototype.filter() to only return the unique elements.
You can wrap it into a helper similar to this:
var concatArraysUniqueWithSort = function (thisArray, otherArray) {
var newArray = thisArray.concat(otherArray).sort(function (a, b) {
return a > b ? 1 : a < b ? -1 : 0;
});
return newArray.filter(function (item, index) {
return newArray.indexOf(item) === index;
});
};
Note that the custom sort function works with numeric elements only, so if you want to use it for strings or mix strings with numbers you have to update it off course to take those scenarios into account, though the rest should not change much.
Use it like this:
var arr1 = [1, 3, 4, 5, 6];
var arr2 = [4, 5, 6, 8, 9, 10];
var arrAll = concatArraysUniqueWithSort(arr1, arr2);
arrAll will now be [1, 3, 4, 5, 6, 8, 9, 10]
DEMO - concatenate 2 arrays, sort and remove duplicates
There is many ways of doing this I'm sure. This was just the most concise I could think off.
merge two or more arrays + remove duplicities + sort()
jQuery.unique([].concat.apply([],[[1,2,3,4],[1,2,3,4,5,6],[3,4,5,6,7,8]])).sort();
One line solution using just javascript.
var Arr1 = [1,3,4,5,6];
var Arr2 = [4,5,6,8,9,10];
const sortedUnion = [... new Set([...Arr1,... Arr2].sort((a,b)=> a-b))]
console.log(sortedUnion)
This looks like a job for Array.prototype.indexOf
var arr3 = arr1.slice(), // clone arr1 so no side-effects
i; // var i so it 's not global
for (i = 0; i < arr2.length; ++i) // loop over arr2
if (arr1.indexOf(arr2[i]) === -1) // see if item from arr2 is in arr1 or not
arr3.push(arr2[i]); // it's not, add it to arr3
arr3.sort(function (a, b) {return a - b;});
arr3; // [1, 3, 4, 5, 6, 8, 9, 10]
a = [1, 2, 3]
b = [2, 3, 4]
$.unique($.merge(a, b)).sort(function(a,b){return a-b}); -> [1, 2, 3, 4]
Update:
This is a bad idea, since the 'unique' function is not meant for use on numbers or strings.
However, if you must then the sort function needs to be told to use a new comparator since by default it sorts lexicographically.
Using underscore.js:
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]).sort(function(a,b){return a-b});
=> [1, 2, 3, 10, 101]
This example is taken directly from underscore.js, a popular JS library which complements jQuery
I did that as follows, where t1 and t2 are my two tables.
The first command put the values of the table t2 to the t1. The second command removes the duplicate values from the table.
$.merge(t1, t2);
$.unique(t1);
function sortUnique(matrix) {
if(matrix.length < 1 || matrix[0].length < 1) return [];
const result = [];
let temp, ele;
while(matrix.length > 0) {
temp = 0;
for(let j=0; j<matrix.length; j++) {
if(matrix[j][0] < matrix[temp][0]) temp = j;
}
if(result.length === 0 || matrix[temp][0] > result[result.length-1]) {
result.push(matrix[temp].splice(0,1)[0]);
} else {
matrix[temp].splice(0,1);
}
if(matrix[temp].length===0) matrix.splice(temp, 1);
}
return result;
}
console.log(sortUnique([[1,4,8], [2,4,9], [1,2,7]]))
Using JavaScript ES6 makes it easier and cleaner. Try this:
return [...Arr1, ...Arr2].filter((v,i,s) => s.indexOf(v) === i).sort((a,b)=> a - b);
and there you have it. You could build it in a function like:
function mergeUniqueSort(Arr1, Arr2){
return [...Arr1, ...Arr2].filter((v,i,s) => s.indexOf(v) === i).sort((a,b)=> a - b);
}
and that settles it. You can also break it down using ES6. Use a Spread Operator to combine arrays:
let combinedArrays = [...Arr1, ...Arr2]
then get the unique elements using the filter function:
let uniqueValues = combinedArrays.filter((value, index, self ) => self.indexOf(value) === index)
Lastly you now sort the uniqueValue object:
let sortAscending = uniqueValues.sort((a-b) => a - b) // 1, 2, 3, ....10
let sortDescending = uniqueValues.sort((b-a) => b - a) // 10, 9, 8, ....1
So you could use any part, just in case.