Правильно ли использовать плоскую карту таким образом?
В основном, отвечая на один из вопросов о SO, связанных со сглаживанием вложенных массивов, я ответил на вопрос с использованием рекурсивного сглаживания.
var exampleArray = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]] ];
function findArrayLengths(input) {
return input.reduce((op,cur)=>{
return Array.isArray(cur) ? op.concat(findArrayLengths(cur)) : op.concat(cur)
},[])
}
let op = exampleArray.map(e=>{
return findArrayLengths(e).length
})
console.log(op);
Но я видел, что этот код также, кажется, работает нормально (плоский с бесконечной глубиной), я немного читал об Array.prototype.Flat
var arr = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]], [[1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]]] ];
let op = arr.map(e=> e.flat(Infinity).length);
console.log(op);
Так что вопрос в том. это правильный способ сделать глубокое сглаживание с плоской, как это или есть последствия.?
Вот ссылка на этот вопрос, и вы можете проверить больше здесь /questions/45453407/vyipusk-prostoj-kartyi-massivov-javascript/45453419#45453419
2 ответа
Вот способ es6, хотя в дальнейшем он может быть использован с использованием .reduce
вместо forEach
const exampleArray = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]] ];
const flatten = (items) => {
const flat = [];
items.forEach(item => {
if (Array.isArray(item)) {
flat.push(...flatten(item));
} else {
flat.push(item);
}
});
return flat;
}
const do_flat = (arr) => arr.map( (curr) => flatten(curr).length);
const output = do_flat(exampleArray);
console.log({output});
это правильный способ сделать глубокое сглаживание с плоской, как это или есть последствия.?
Никаких последствий, Array#flat(Infinity)
хорошо Просто проблема с браузером / обратной совместимостью.
Я был не уверен, что спецификация определяет, как бороться с depth
и поэтому Infinity
является безопасным значением для всего браузера; Короче говоря, он определен и безопасен в использовании.
Но у меня есть проблема с вашим резервным кодом. С помощью Array#concat()
То, как вы делаете, создает много промежуточных (и ненужных) массивов.
Лучший подход был бы:
var exampleArray = [
[1, 2, 3, 4],
[1, 2, [1, 2, 3]],
[1, 2, 3, 4, 5, [1, 2, 3, 4, [1, 2, 3, 4]]]
];
function _flatten(acc, value) {
if (Array.isArray(value)) {
return value.reduce(_flatten, acc);
}
acc.push(value);
return acc;
}
function flatten(array) {
return array.reduce(_flatten, []);
}
console.log(exampleArray.map(e => flatten(e).length));
//or since you already named your function `findArrayLength`
function _findArrayLength(count, value) {
return Array.isArray(value) ? value.reduce(_findArrayLength, count) : count + 1;
}
function findArrayLength(array) {
return array.reduce(_findArrayLength, 0);
}
console.log(exampleArray.map(findArrayLength));
.as-console-wrapper{top:0;max-height:100%!important}
Или более общая реализация
var exampleArray = [
[1, 2, 3, 4],
[1, 2, [1, 2, 3]],
[1, 2, 3, 4, 5, [1, 2, 3, 4, [1, 2, 3, 4]]]
];
function reduceRecursive(fn, init) {
function _(acc, value, index, array) {
return Array.isArray(value) ? value.reduce(_, acc) : fn(acc, value, index, array);
}
return function(array){
return array.reduce(_, typeof init === "function" ? init() : init);
}
}
var flatten = reduceRecursive(function(result, value) {
result.push(value);
return result;
}, Array);
console.log(exampleArray.map(e => flatten(e).length));
var findArrayLength = reduceRecursive(function(count) {
return count + 1;
}, 0);
console.log(exampleArray.map(findArrayLength));
.as-console-wrapper{top:0;max-height:100%!important}