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);
Related
I have an array of arrays of arrays and I'm trying to remove an element from a sub-sub array. The problem is the element is removed from all my sub-sub arrays. See code below:
let list = Array(9).fill(Array(9).fill([1,2,3,4,5,6,7,8,9]));
list[0][0].splice(3,1);
console.log(list[0][0],list[2][1],list)
Please let me know if you know how to solve that.
Array.prototype.fill fills the array with the exact same value that was provided to it. This is not a problem when filling the array with immutable values (like numbers, strings) but it's usually a problem with mutable values (like objects, arrays).
So, if you mutate one value in the array you would notice the change at all other places because all of them refer to the exact same value. Refer to example below for better understanding.
let nums = [1];
let arr = Array(2).fill(nums);
// mutating nums
nums[0] = 5;
// the change is visible in arr as well
console.log(arr[0]); // [ 5 ]
// and it's visible at both the indicies
console.log(arr[1]); // [ 5 ]
// mutating arr
arr[0][0] = 10;
// change is visible in nums as well
console.log(nums); // [ 10 ]
// and also at index 1
console.log(arr[1]); // [ 10 ]
You can use Array.from instead.
let list = Array.from({ length: 9 }, () =>
Array.from({ length: 9 }, () => [1, 2, 3, 4, 5, 6, 7, 8, 9])
);
list[0][0].splice(3, 1);
console.log(list[0][0]); // [ 1, 2, 3, 5, 6, 7, 8, 9 ]
console.log(list[1][0]); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
I have a need to add or prepend elements at the beginning of an array.
For example, if my array looks like below:
[23, 45, 12, 67]
And the response from my AJAX call is 34, I want the updated array to be like the following:
[34, 23, 45, 12, 67]
Currently I am planning to do it like this:
var newArray = [];
newArray.push(response);
for (var i = 0; i < theArray.length; i++) {
newArray.push(theArray[i]);
}
theArray = newArray;
delete newArray;
Is there a better way to do this? Does JavaScript have any built-in functionality that does this?
The complexity of my method is O(n) and it would be really interesting to see better implementations.
Use unshift. It's like push, except it adds elements to the beginning of the array instead of the end.
unshift/push - add an element to the beginning/end of an array
shift/pop - remove and return the first/last element of an array
A simple diagram...
unshift -> [array] <- push
shift <- [array] -> pop
and chart:
add remove start end
push X X
pop X X
unshift X X
shift X X
Check out the MDN Array documentation. Virtually every language that has the ability to push/pop elements from an array will also have the ability to unshift/shift (sometimes called push_front/pop_front) elements, you should never have to implement these yourself.
As pointed out in the comments, if you want to avoid mutating your original array, you can use concat, which concatenates two or more arrays together. You can use this to functionally push a single element onto the front or back of an existing array; to do so, you need to turn the new element into a single element array:
const array = [3, 2, 1]
const newFirstElement = 4
const newArray = [newFirstElement].concat(array) // [ 4, 3, 2, 1 ]
console.log(newArray);
concat can also append items. The arguments to concat can be of any type; they are implicitly wrapped in a single-element array, if they are not already an array:
const array = [3, 2, 1]
const newLastElement = 0
// Both of these lines are equivalent:
const newArray1 = array.concat(newLastElement) // [ 3, 2, 1, 0 ]
const newArray2 = array.concat([newLastElement]) // [ 3, 2, 1, 0 ]
console.log(newArray1);
console.log(newArray2);
var a = [23, 45, 12, 67];
a.unshift(34);
console.log(a); // [34, 23, 45, 12, 67]
With ES6, use the spread operator ...:
Demo
var arr = [23, 45, 12, 67];
arr = [34, ...arr]; // RESULT : [34,23, 45, 12, 67]
console.log(arr)
Another way to do that is through concat:
var arr = [1, 2, 3, 4, 5, 6, 7];
console.log([0].concat(arr));
The difference between concat and unshift is that concat returns a new array. The performance between them could be found here.
function fn_unshift() {
arr.unshift(0);
return arr;
}
function fn_concat_init() {
return [0].concat(arr)
}
Here is the test result:
Quick Cheatsheet:
The terms shift/unshift and push/pop can be a bit confusing, at least to folks who may not be familiar with programming in C.
If you are not familiar with the lingo, here is a quick translation of alternate terms, which may be easier to remember:
* array_unshift() - (aka Prepend ;; InsertBefore ;; InsertAtBegin )
* array_shift() - (aka UnPrepend ;; RemoveBefore ;; RemoveFromBegin )
* array_push() - (aka Append ;; InsertAfter ;; InsertAtEnd )
* array_pop() - (aka UnAppend ;; RemoveAfter ;; RemoveFromEnd )
Using ES6 destructuring (avoiding mutation off the original array):
const newArr = [item, ...oldArr]
Without Mutating
Actually, all unshift/push and shift/pop mutate the source array.
The unshift/push add an item to the existed array from begin/end and shift/pop remove an item from the beginning/end of an array.
But there are few ways to add items to an array without a mutation. the result is a new array, to add to the end of array use below code:
const originArray = ['one', 'two', 'three'];
const newItem = 4;
const newArray = originArray.concat(newItem); // ES5
const newArray2 = [...originArray, newItem]; // ES6+
To add to begin of original array use below code:
const originArray = ['one', 'two', 'three'];
const newItem = 0;
const newArray = (originArray.slice().reverse().concat(newItem)).reverse(); // ES5
const newArray2 = [newItem, ...originArray]; // ES6+
With the above way, you add to the beginning/end of an array without a mutation.
You have an array: var arr = [23, 45, 12, 67];
To add an item to the beginning, you want to use splice:
var arr = [23, 45, 12, 67];
arr.splice(0, 0, 34)
console.log(arr);
Cheatsheet to prepend new element(s) into the array
1. Array#unshift
const list = [23, 45, 12, 67];
list.unshift(34);
console.log(list); // [34, 23, 45, 12, 67];
2. Array#splice
const list = [23, 45, 12, 67];
list.splice(0, 0, 34);
console.log(list); // [34, 23, 45, 12, 67];
3. ES6 spread...
const list = [23, 45, 12, 67];
const newList = [34, ...list];
console.log(newList); // [34, 23, 45, 12, 67];
4. Array#concat
const list = [23, 45, 12, 67];
const newList = [32].concat(list);
console.log(newList); // [34, 23, 45, 12, 67];
Note: In each of these examples, you can prepend multiple items by providing more items to insert.
If you need to continuously insert an element at the beginning of an array, it is faster to use push statements followed by a call to reverse, instead of calling unshift all the time.
Benchmark test: http://jsben.ch/kLIYf
Using splice we insert an element to an array at the begnning:
arrName.splice( 0, 0, 'newName1' );
If you want to push elements that are in an array at the beginning of your array, use <func>.apply(<this>, <Array of args>):
const arr = [1, 2];
arr.unshift.apply(arr, [3, 4]);
console.log(arr); // [3, 4, 1, 2]
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);
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'm retrieving some data and the data looks like this:
1, 2, 3, 4, 5
6, 7, 8, 9, 10
11, 12, 13, 14, 15
I want it to look like this
[
[[1],[2],[3],[4],[5]],
[[6],[7],[8],[9],[10]],
[[11],[12],[13],[14],[15]]
]
So that I may address the array like a matrix, data[0][1] would be "2".
Through this answer, it's almost there, but not quite. I'm having trouble getting to look like what I want.
How about this, assuming this accurately represents your input data:
var data = "1,2,3,4,5\n6,7,8,9,10\n11,12,13,14,15";
var matrix = data.split('\n').map(function(val) {
return val.split(',');
});
Note that your specified output is probably not what you meant. Each number should probably not be its own single-item array. Instead, the code above produces:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 1]
]
Which means matrix[0][1] would return 2, as opposed to having to do matrix[0][1][0]
Edit: As noted in the comments, I've left it up to you to ensure this fits your browser-support needs. This also goes for every other line of JS you ever write...
NOTE - If you need to iterate through an array use a simple for, and not a for..in
for..in returns the items in no guaranteed order which is probably not what you want when working with an array
for..in returns not the just the array elements, but anything added to the Array prototype (meaning if you use a traditional for loop you can be completely confident the code will work regardless of what external libraries may be included on the page. No need to worry that some other coder has added properties/methods to Array.prototype)
If \n is the line separator and , is the item seperator within a line, you can use something like:
/* assuming data is already filled like:
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
*/
var arr = data.split("\n"), arr2 = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] != '') arr2.push(arr[i].split(','));
}
console.log(arr2);
/* arr2 will be like:
[
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
]
*/
var data = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'.split(',');
var matrixData = [];
while (data.length > 0) {
matrixData.push(data.splice(0, 5));
}
document.write(matrixData[0][1]);
Edit: If you get the data as a simple array of numbers