Правильно ли использовать плоскую карту таким образом? - PullRequest
0 голосов
/ 19 декабря 2018

В основном, отвечая на один из вопросов о 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);

Так что вопрос в том.это правильный способ сделать глубокое сглаживание с плоской, как это, или есть последствия. ?

Вот ссылка на этот вопрос, и вы можете проверить больше здесь https://stackoverflow.com/a/53844891/9624435

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

- это правильный способ сделать глубокое выравнивание с такой плоскостью или есть последствия.?

Никаких последствий, Array#flat(Infinity) в порядке .Просто проблема с браузером / обратной совместимостью.

Я не был уверен, что spec определяет, как обращаться с переданным 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}
0 голосов
/ 19 декабря 2018

Вот способ 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});
...