preface
During the interview, the interviewer asked: How to implement flat method? At that time, handwriting was not perfect. Later, I went back to review and found that there were many interviewers who required handwriting array to flatten (flatten) the interview method. These include: Pinduoduo, Xiaomi, Meituan, Didi, Shopee, Youzan, etc. Handwriting flat method is a very basic interview question, which is usually used in the written test or the first round of the interview. It mainly tests the basic ability of handwriting code. Today, let’s relearn the method of array flat from understanding the characteristics of flat to realizing flat and answering the serial questions of the interviewer.
Making poking me
A code summaryArray.prototype.flat()
features
Array.prototype.flat() array.prototype.flat () This article is called: array flatten
const animals = ["🐷"["🐶"."🐂"], ["🐎"["🐑"["🐲"]], "🐛"]].// If no parameter is passed, the layer is flattened by default
animals.flat();
// ["🐷", "🐶", "🐂", "🐎", [" byte ", [" byte "]], "password "]
// Pass an integer argument, which is the number of layers "leveled"
animals.flat(2);
// ["🐷", "🐶", "🐂", "🐎", "🐶", [" byte "], "password "]
// When the Infinity keyword is used as an argument, it is converted to a one-dimensional array no matter how many layers are nested
animals.flat(Infinity);
// ["🐷", "🐶", "🐂", "🐎", "byte "," byte ", "byte "," password "]
// Passing an integer <=0 returns the original array, not "leveled"
animals.flat(0);
animals.flat(- 10);
/ / / "🐷," [" 🐶 ", "🐂"], [" 🐎, "[" 🐑," [" 🐲 "]], "🐛"]].
// If the array has a vacancy, flat() skips the vacancy.
["🐷"."🐶"."🐂"."🐎",,].flat();
// ["🐷", "🐶", "🐂", "🐎"]
Copy the code
Array.prototype.flat()
Characteristics of summary
Array.prototype.flat()
Used to “flatten” a nested array into a one-dimensional array. This method returns a new array with no effect on the original data.- When no parameter is passed, a layer is “leveled” by default, and an integer can be passed to indicate the number of layers you want to “leveled”.
- The incoming
< = 0
Will return the original array, not “flattened” Infinity
When a keyword is used as a parameter, it is converted to a one-dimensional array no matter how many layers are nested- If the original array is empty,
Array.prototype.flat()
Will skip the empty space.
“Asked the interviewer
First question: Implement a simple array flattenflat
function
First, we’ll spend a bit of time exploring how to implement a simple array flat function, introducing various implementation schemes in detail, and then try to catch up with the interviewer’s continuous questioning.
Implementation approach
To implement flat, the idea is very simple: To implement flat with an array, all we need to do is find elements in the array that are of the array type and expand them. So that’s the key idea of the flat array method.
With an idea in mind, we need to solve the difficulties we need to overcome to achieve this idea:
- The first problem is to iterate over each element of the array;
- The second problem is to determine whether an element is an array;
- The third problem is to expand the elements of the array by one level;
Iterate over the scheme of the number group
There are many ways to iterate over an array and get an array element, including but not limited to the following:
The for loop
for... of
for... in
forEach()
entries()
keys()
values()
reduce()
map()
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }];
// There are too many ways to iterate over a group of numbers. This article enumerates only the common ones
/ / a for loop
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// for... of
for (let value of arr) {
console.log(value);
}
// for... in
for (let i in arr) {
console.log(arr[i]);
}
/ / the forEach loop
arr.forEach(value= > {
console.log(value);
});
/ / entries ()
for (let [index, value] of arr.entries()) {
console.log(value);
}
// keys()
for (let index of arr.keys()) {
console.log(arr[index]);
}
// values()
for (let value of arr.values()) {
console.log(value);
}
// reduce()
arr.reduce((pre, cur) = > {
console.log(cur); } []);// map()
arr.map(value= > console.log(value));
Copy the code
Anything that can go through an array and get to every element in the array is a viable solution.
Determine the element is an array scheme
instanceof
constructor
Object.prototype.toString
isArray
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }];
arr instanceof Array
// true
arr.constructor === Array
// true
Object.prototype.toString.call(arr) === '[object Array]'
// true
Array.isArray(arr)
// true
Copy the code
Description:
-
The instanceof operator assumes that there is only one global environment. If a web page contains multiple frames, multiple global environments, and if you pass an array from one frame to another, the array passed in has a different constructor than the array created natively in the second frame. (So it would be inaccurate in this case)
-
The typeof operator returns object for typing an array
-
Since constructor can be overridden, it is not guaranteed to be an array.
const str = 'abc'; str.constructor = Array; str.constructor === Array // true Copy the code
Expands the elements of an array at one level
- The extension operator +
concat
The concat() method is used to merge two or more arrays, adding an extension operator during concatenation to expand a layer of arrays. See the code below for details.
conca
t +apply
With apply, the second argument passed to the binding scope is an array or array-like object whose array elements are passed as separate arguments to the func function. That is, when the apply function is called, the array is passed into the function to be executed one by one, that is, the array is expanded.
toString
+split
The toString + split method is not recommended because manipulating strings is dangerous. In my last article, I did a string manipulation case that was criticized by many of my friends. If all the elements in the array are numbers, toString +split works and is done in one step.
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }];
// Extend operator + concat[].concat(... arr)/ / [1, 2, 3, 4, 1, 2, 3, [1, 2, 3, [1, 2, 3]], 5, "string", {name: "play iron eggs students"});
// concat + apply
[].concat.apply([], arr);
/ / [1, 2, 3, 4, 1, 2, 3, [1, 2, 3, [1, 2, 3]], 5, "string", {name: "play iron eggs students"});
// toString + split
const arr2 =[1.2.3.4[1.2.3[1.2.3[1.2.3]]]]
arr2.toString().split(', ').map(v= >parseInt(v))
// [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3]
Copy the code
After summing up the three difficulties to be solved, we can easily implement a version of array flat function.
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }];
// concat + recursive
function flat(arr) {
let arrResult = [];
arr.forEach(item= > {
if (Array.isArray(item)) {
arrResult = arrResult.concat(arguments.callee(item)); / / recursion
// Or use the extension operator
// arrResult.push(... arguments.callee(item));
} else{ arrResult.push(item); }});return arrResult;
}
flat(arr)
/ / [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", {name: "play iron eggs students"});
Copy the code
Here, congratulations on your success in getting the interviewer’s basic recognition of your ability to rip code 🎉. But the interviewer will often go beyond that and continue to test a candidate’s abilities.
Second question: Yesreduce
implementationflat
function
I’ve seen a lot of interviewers who like to ask interviewees by name to implement flat function directly with reduce. Wonder why? We’ll see why later in this article when we consider array empty cases. The idea is the same.
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }]
// First expand a layer using reduce
arr.reduce((pre, cur) = > pre.concat(cur), []);
/ / [1, 2, 3, 4, 1, 2, 3, [1, 2, 3, [1, 2, 3]], 5, "string", {name: "play iron eggs students"});
// Use reduce to expand a layer + recursion
const flat = arr= > {
return arr.reduce((pre, cur) = > {
return pre.concat(Array.isArray(cur) ? flat(cur) : cur); } []); };/ / [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", {name: "play iron eggs students"});
Copy the code
Third question: Use the idea of a stack implementationflat
function
/ / the stack
function flat(arr) {
const result = [];
const stack = [].concat(arr); // Copy the array elements onto the stack. Assignment directly changes the original array
// If the stack is not empty, the loop is iterated
while(stack.length ! = =0) {
const val = stack.pop();
if (Array.isArray(val)) { stack.push(... val);// If the array is pushed again and a layer is expanded
} else {
result.unshift(val); // If it's not an array, put it in the result array}}return result;
}
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }]
flat(arr)
/ / [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", {name: "play iron eggs students"});
Copy the code
Q4: Control the number of leveling layers by passing in integer parameters
// reduce + recursion
function flat(arr, num = 1) {
return num > 0
? arr.reduce(
(pre, cur) = >
pre.concat(Array.isArray(cur) ? flat(cur, num - 1) : cur),
[]
)
: arr.slice();
}
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }]
flat(arr, Infinity);
/ / [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", {name: "play iron eggs students"});
Copy the code
Fifth question: UseGenerator
implementationflat
function
function* flat(arr, num) {
if (num === undefined) num = 1;
for (const item of arr) {
if (Array.isArray(item) && num > 0) { // num > 0
yield* flat(item, num - 1);
} else {
yielditem; }}}const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }]
// After a Generator is called, the function does not execute and returns not the result of the function's operation but a pointer object to the internal state.
// That is, the Iterator Object. So we're going to use an extension operator to get the result
[...flat(arr, Infinity)]
/ / [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", {name: "play iron eggs students"});
Copy the code
Q6: Implementations are rewritten on the prototype chainflat
function
Array.prototype.fakeFlat = function(num = 1) {
if (!Number(num) || Number(num) < 0) {
return this;
}
let arr = this.concat(); // Get the array to call the fakeFlat function
while (num > 0) {
if (arr.some(x= > Array.isArray(x))) {
arr = [].concat.apply([], arr); // If there are still elements in the array and num > 0, expand the array further
} else {
break; // There are no array elements in the array and if num is still greater than 0, stop the loop.
}
num--;
}
return arr;
};
const arr = [1.2.3.4[1.2.3[1.2.3[1.2.3]]].5."string", { name: "Student with Iron Balls" }]
arr.fakeFlat(Infinity)
/ / [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", {name: "play iron eggs students"});
Copy the code
Q7: Consider the case of an array empty
According to the flat feature we summarized at the beginning, flat function execution will skip vacancies. Most array methods in ES5 will skip empty Spaces, including forEach(), filter(), reduce(), every() and some().
Therefore, we can use the above methods to realize the feature of flat skipping vacancies
// reduce + recursion
Array.prototype.fakeFlat = function(num = 1) {
if (!Number(num) || Number(num) < 0) {
return this;
}
let arr = [].concat(this);
return num > 0
? arr.reduce(
(pre, cur) = >
pre.concat(Array.isArray(cur) ? cur.fakeFlat(--num) : cur),
[]
)
: arr.slice();
};
const arr = [1[3.4],,,]; arr.fakeFlat()/ / [1, 3, 4]
// foEach + recursion
Array.prototype.fakeFlat = function(num = 1) {
if (!Number(num) || Number(num) < 0) {
return this;
}
let arr = [];
this.forEach(item= > {
if (Array.isArray(item)) {
arr = arr.concat(item.fakeFlat(--num));
} else{ arr.push(item); }});return arr;
};
const arr = [1[3.4],,,]; arr.fakeFlat()/ / [1, 3, 4]
Copy the code
Read more:Because the rules for dealing with vacancies are very inconsistent, it is recommended that vacancies be avoided.
ES5’s treatment of empty seats is very inconsistent, ignoring empty seats in most cases.
forEach()
.filter()
.reduce()
.every()
和some()
All jump over the empty space.map()
The void is skipped, but the value is preserved.join()
和toString()
Will treat the empty space asundefined
And theundefined
和null
Will be processed as an empty string.
ES6 explicitly converts the void toundefined
.
entries()
,keys()
,values()
,find()
andfindIndex()
Will process the empty space intoundefined
.for... of
The loop traverses the empty space.fill()
Empty Spaces are treated as normal array positions.copyWithin()
Will copy with the empty space.- Extended operator (
.
) will also convert the empty space toundefined
. Array.from
Method will convert the empty space of the array toundefined
.
conclusion
In fact, it is not just about writing code. In the process of writing code, there will be a variety of knowledge points and the boundary of the code. Although most of the time, the interviewer will not be so creepy as to continuously question the interviewer about the flat implementation and tear several versions by hand, it is not uncommon for the interviewer to ask for a more perfect version of the code you wrote. As long as we settle down and lay a solid foundation, no matter how the interviewer asks, we can cope with it freely. There are more than just the versions listed in this article. Typing your own code is the best step forward. Write your own version in the comments section or in the issue section.
Today I learned. If you’ve learned it, just click “like” 👍
At the end of the article eggs
I remember Posting my first technical post in Denver two weeks ago Sunday, around 10 PM. By Monday afternoon I had received over 70 likes. I was very flattered and satisfied with my expectation of 70 likes. But to my surprise, the article got 1000+ likes in about 5 days, and the level of The nuggets went up to level 3 directly. I was really happy to be recognized by everyone. The code of that article was very bad in a certain scheme. Thank you very much for pointing out my mistakes in the comment section, and also for giving me a thumbs-up. Thank you very much for your thumbs-up. At the same time, I also hope to become friends with you in study and life, and exchange technology and life together. Play iron eggs students are very welcome to add my WeChat and add group chat ~ play iron eggs classmates also conveniently opened a public, record their main technical articles and my own life, also have a large collection of front-end online learning materials are put in the public number, you can also with focus on a wave of oh, can also in the private chat I push you oh ~
Recommended reading
You don’t know the power of json.stringify ()