1 what is flattening?
I went to Wikipedia. There is no direct explanation about flattening, only an explanation of flattening organization.
First, let's talk about the organization opposite to flattening: Pyramid organization. As we all know, its hierarchical structure is a pyramid shape.
Flat organization, also known as horizontal organization, is an organization with little or no intermediate management between employees and bosses.
The pyramid organization is on the left and the flat organization is on the right. It can be seen that the level of flat organization is few, and the constituent units (people) in the grass-roots level are the most.
2 what is array flattening
['a', 'b', 'c'] / / this is an array with three elements. It is a one-dimensional array (there is no array nesting). [['a', 'b', 'c','d ',' e ',' f ']] is an array as a whole, but the elements in it are arrays, that is, nested arrays in the array, which is a two-dimensional array
And so on·····
['a', 'b', 'c']] / / 3-dimensional array ['a', 'b', 'c', '[...]]] / / n-dimensional array flattening is to convert multi-dimensional array into one-dimensional array. (it can be associated with the figure above... Similar to the expansion of an array)
3 method of flattening array
3.1 es6 New method provided by flat(depth)
let a = [1,[2,3]]; a.flat(); // [1,2,3] a.flat(1); //[1,2,3]
The parameter depth in the flat(depth) method represents the depth of expanding the nested array. The default value is 1
So we can add parameter 1, or directly call flat() to flatten the 2-dimensional array. If we can know the dimension of the array in advance and flatten the array, the value of parameter depth is the dimension of the array minus one.
let a = [1,[2,3,[4,[5]]]]; a.flat(4-1); // [1,2,3,4,5] A is a 4-dimensional array
In fact, there is a simpler way to directly turn the target array into a one-dimensional array without knowing the dimension of the array. Set the value of depth to Infinity.
let a = [1,[2,3,[4,[5]]]]; a.flat(Infinity); // [1,2,3,4,5] A is a 4-dimensional array
3.2 for loop
var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]]; function flatten(arr) { var res = []; for(let i = 0, length = arr.length; i < length; i++) { if(Array.isArray(arr[i])) { res = res.concat(flatten(arr[i])); //concat does not change the original array //res.push(...flatten(arr[i])); // Extension operator } else{ res.push(arr[i]); } } return res; } flatten(arr1); //[1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
Use the for loop to traverse each item of the array and judge it. If it is not an array, execute the push operation. If it is the normalization of the array, execute the function again (recursion) until the whole array is traversed.
ps:... And concat() can be replaced, so they can be regarded as two methods.
3.3 while loop
var arr1 = [1, 2, [3], [1, 2, 3, [4, [2, 3, 4]]]]; function flatten(arr) { while(arr.some(item => Array.isArray(item))) { arr = [].concat(...arr); //arr = Array.prototype.concat.apply([],arr); } return arr; } flatten(arr1); //[1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
3.4 reduce method
var arr1 = [1, 2, [3], [1, 2, 3, [4, [2, 3, 4]]]]; function flatten(arr) { return arr.reduce((res,next) =>{ return res.concat(Array.isArray(next)? flatten(next) : next); },[]); }
3.5 using stack infinite anti nesting multi-layer nested array
var arr1 = [1, 2, [3], [1, 2, 3, [4, [2, 3, 4]]]]; function flatten(input) { const stack = [...input]; //Ensure that the original array will not be destroyed const result = []; while(stack.length) { const first = stack.shift(); if(Array.isArray(first)) { stack.unshift(...first); } else{ result.push(first); } } return result; } flatten(arr1); //[1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
In fact, this method is not very complicated. The principle of recursion is not used here to judge the length of the stack array. Remove each item from the array from front to back (at this time, the length of the stack array is reduced by one), and judge. If it is not an array, execute the push operation, and the item will be removed. It is the grouping of numbers. After the array is expanded, execute the unshift operation and add it to the front of the stack array, At this time, the length of the stack array will increase. In this way, we will continue to judge and expand until each item is removed.
PS: the [... input] at the beginning of 1 is to ensure that the passed in array will not be destroyed.
2 the above shift(),unshift(), can be replaced by pop() and push(), but the reverse() operation should be performed before return
3.6 if the items of the array are all numbers, you can use join(), toString()
If the items of the array are all numbers, you can use join(), toString() to flatten them.
function flatten(input) { return input.toString().split(',').map(item => +item); // return input.join().split(',').map(item => +item); // return input.join(',').split(',').map(item => +item); } flatten(arr1); //[1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
The principle is very simple. First convert the array into a string. This process will remove [] and then call the split() method to convert it into an array. Finally, don't forget to convert each item into an array, that is, call the map() method.
- ps: the toString () method of the array is defined in array On the prototype, toString() will be executed for each item of the array
- Then it is spliced into a string, so even if the array is nested, the nested array will execute the toString method.
- ----Here is my personal understanding.
- The above explanation is also not rigorous. Some leaders will say that there is no toString() method on undefined and null,
- [null,undefined].toString();//"null,undefined"
- It can be understood here that the js engine made a judgment and executed the String() method. Ensure that the toString() method of the array will not report an error.
3.7 new method flatMap() of ES6; The array can be expanded in 2 dimensions.
A new method of es6 array flatMap(); Can be used to expand 2-dimensional arrays. The flatmap () method is similar to first executing the map() of the array (equivalent to executing Array.prototype.map()), and then executing the flat() method (expanding one layer) on the array composed of return values.
var arr = [["this", "day", "day", "gas", "no", "wrong"],[""],["Good morning!", "upper", "good"]]; arr.flatMap(item => item); //["today", "day", "day", "Qi", "no", "wrong", "morning", "go", "good"]
Unlike map(), flatMap() does not change the original array
4 Summary
There are many ways to flatten the array. If you want to force the use of call,apply, etc., you may have to add several methods. Except for flat(), the other methods must traverse the array and judge. Except for the method of 3.5, they basically need recursion. Wait until you have time. Under the supplement, the performance of each method is different. If it is only a number, it is recommended to use the last method.
5 subsequent performance problems
5.1 generate n-dimensional array
let arr =[]; for(let i = 199; i> 0;i--){ arr = [i].concat([arr]); //Generate a 199 dimensional array }
There are two main reasons for generating 199 dimensional arrays instead of larger arrays: 1. Deep dimensional arrays will not appear in actual projects. Even JSON data is unlikely to exceed 10 dimensions. After all, parsing is very cumbersome. 2. This is for the convenience of testing. If the dimension set is too deep, such as 9999, some methods of flattening arrays will report errors.
5.2 performance test
1. The best performance is the false() of es6
2. The worst is while() reduce()
3. The remaining methods are not very different.