У меня есть массив JavaScript, как:
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
Как бы я мог объединить отдельные внутренние массивы в один, например:
["$6", "$12", "$25", ...]
javascript
arrays
flatten
Энди
источник
источник
reduce
+,concat
представляют собой O ((N ^ 2) / 2), где в качестве принятого ответа (всего один вызовconcat
) будет не более O (N * 2) в плохом браузере и O (N) в Неплохо. Также решение Denys оптимизировано для актуального вопроса и в 2 раза быстрее, чем одиночноеconcat
. Дляreduce
людей забавно чувствовать себя клевым, когда пишу крошечный код, но, например, если бы в массиве было 1000 одноэлементных подмассивов, все решения Redu + Concat выполняли бы 500500 операций, в то время как один конкат или простой цикл выполнял бы 1000 операций.[].concat(...array)
array.flat(Infinity)
гдеInfinity
максимальная глубина для выравнивания.Ответы:
Вы можете использовать
concat
для объединения массивов:Использование
apply
методаconcat
просто примет второй параметр в качестве массива, поэтому последняя строка идентична этой:Существует также
Array.prototype.flat()
метод (представленный в ES2019), который можно использовать для выравнивания массивов, хотя он доступен только в Node.js, начиная с версии 11, и совсем не доступен в Internet Explorer .источник
concat
это не изменяет исходный массив, поэтомуmerged
массив останется пустым после вызоваconcat
. Лучше сказать что-то вроде:merged = merged.concat.apply(merged, arrays);
var merged = [].concat.apply([], arrays);
кажется, работает нормально, чтобы получить его на одной строке. Отредактируйте: как уже показывает ответ Никиты.Array.prototype.concat.apply([], arrays)
.var merged = [].concat(...arrays)
Вот короткая функция, которая использует некоторые из новых методов массива JavaScript, чтобы сгладить n-мерный массив.
Применение:
источник
flat
первого вызова анонимной функции, переданного вreduce
. Если он не указан, то первый вызовreduce
связывает первое значение из массиваflat
, что в конечном итоге приведет к тому , что он будет1
связанflat
в обоих примерах.1.concat
это не функция.const flatten = (arr) => arr.reduce((flat, next) => flat.concat(next), []);
const flatten = (arr) => arr.reduce((flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []);
Существует запутанно скрытый метод, который создает новый массив без изменения исходного:
источник
[].concat([[1],[2,3],[4]]...)
[[1],[2,3],[4]]
в результате. Решение, которое дает @Nikita, является правильным для CoffeeScript и JS.[].concat([1],[2,3],[4],...)
....
Являются фактическим кодом, а не некоторые многоточие точки.Лучше всего это сделать с помощью функции сокращения JavaScript.
Или с ES2015:
JS-скрипка
Документы Mozilla
источник
[]
и никакие дальнейшие проверки не требуются .arrays.reduce((flatten, arr) => [...flatten, ...arr])
Для этого существует новый нативный метод flat .
(По состоянию на конец 2019 года,
flat
теперь публикуется в стандарте ECMA 2019, иcore-js@3
(библиотека babel) включает его в свою библиотеку polyfill )источник
Большинство ответов здесь не работают с огромными (например, 200 000 элементов) массивами, и даже если они работают, они работают медленно. Ответ polkovnikov.ph имеет лучшую производительность, но он не работает для глубокого выравнивания.
Вот самое быстрое решение, которое работает также для массивов с несколькими уровнями вложенности :
Примеры
Огромные массивы
Он отлично справляется с огромными массивами. На моей машине выполнение этого кода занимает около 14 мс.
Вложенные массивы
Работает с вложенными массивами. Этот код выдает
[1, 1, 1, 1, 1, 1, 1, 1]
.Массивы с разными уровнями вложенности
У него нет проблем с такими массивами, как этот.
источник
RangeError: Maximum call stack size exceeded
). Для массива из 20 000 элементов это занимает 2-5 миллисекунд.Обновление: оказалось, что это решение не работает с большими массивами. Если вы ищете лучшее, более быстрое решение, проверьте этот ответ .
Is просто раскрывает
arr
и передает его в качестве аргументаconcat()
, который объединяет все массивы в один. Это эквивалентно[].concat.apply([], arr)
.Вы также можете попробовать это для глубокого выравнивания:
Смотрите демо на JSBin .
Ссылки на элементы ECMAScript 6, используемые в этом ответе:
Примечание: такие методы, как
find()
функции со стрелками, поддерживаются не всеми браузерами, но это не значит, что вы не можете использовать эти функции прямо сейчас. Просто используйте Babel - он превращает код ES6 в ES5.источник
apply
, я удалил свои комментарии из вашего. Я все еще думаю, что использованиеapply
/ распространение таким способом - плохой совет, но так как никто не заботится ...const flatten = arr => [].concat(...arr)
Вы можете использовать Underscore :
источник
true
второй аргумент .Общие процедуры означают, что нам не нужно переписывать сложность каждый раз, когда нам нужно использовать определенное поведение.
concatMap
(илиflatMap
) это именно то, что нам нужно в этой ситуации.предвидение
И да, вы правильно догадались, он сглаживает только один уровень, который именно так и должен работать
Вообразите некоторый набор данных как это
Хорошо, теперь скажем, что мы хотим напечатать список, который показывает всех игроков, которые будут участвовать в
game
...Если бы наша
flatten
процедура также сглаживала вложенные массивы, мы бы в итоге получили такой результат мусора ...катится глубоко, детка
Это не значит, что иногда вы не хотите сглаживать вложенные массивы - только это не должно быть поведением по умолчанию.
Мы можем сделать
deepFlatten
процедуру с легкостью ...Там. Теперь у вас есть инструмент для каждой работы - один для уничтожения одного уровня вложенности
flatten
и один для уничтожения всех вложенийdeepFlatten
.Может быть, вы можете позвонить
obliterate
или,nuke
если вам не нравится имяdeepFlatten
.Не повторяйте дважды!
Конечно, вышеупомянутые реализации умны и кратки, но использование
.map
последующего вызова to.reduce
означает, что мы фактически делаем больше итераций, чем необходимоИспользование надежного комбинатора, который я вызываю,
mapReduce
помогает свести итерации к минимуму; он принимает функцию отображения, функциюm :: a -> b
сокращенияr :: (b,a) ->b
и возвращает новую функцию сокращения - этот комбинатор лежит в основе преобразователей ; если вам интересно, я написал о них другие ответыисточник
concat
сам по себе не дуют стек, только...
иapply
делает (наряду с очень большими массивами). Я этого не видел. Я просто чувствую себя ужасно прямо сейчас.concat
в Javascript есть другое значение, чем в Haskell. Haskell'sconcat
([[a]] -> [a]
) будет вызванflatten
в Javascript и реализован какfoldr (++) []
(Javascript:foldr(concat) ([])
предполагается, что функции карри). Javascriptconcat
- это странное приложение ((++)
в Haskell), которое может обрабатывать и то,[a] -> [a] -> [a]
и другоеa -> [a] -> [a]
.flatMap
, потому что это именно то, чтоconcatMap
есть:bind
экземплярlist
монады.concatpMap
реализован какfoldr ((++) . f) []
. В переводе на Javascript:const flatMap = f => foldr(comp(concat) (f)) ([])
. Это, конечно, похоже на вашу реализацию безcomp
.Решение для более общего случая, когда в вашем массиве могут быть некоторые элементы, не являющиеся массивами.
источник
Object.defineProperty(Array.prototype,'flatten',{value:function(r){for(var a=this,i=0,r=r||[];i<a.length;++i)if(a[i]!=null)a[i] instanceof Array?a[i].flatten(r):r.push(a[i]);return r}});
flattenArrayOfArrays (arr, 10)
или этоflattenArrayOfArrays(arr, [1,[3]]);
- эти вторые аргументы добавляются к выводу.r
самом деле объединит результаты рекурсии.Чтобы сгладить массив массивов из одного элемента, вам не нужно импортировать библиотеку, простой цикл является и самым простым, и наиболее эффективным решением:
Для даунвотеров: пожалуйста, прочитайте вопрос, не понизьте голос, потому что это не устраивает вашу совсем другую проблему. Это решение является самым быстрым и простым для задаваемого вопроса.
источник
['foo', ['bar']]
до['f', 'bar']
.Как насчет использования
reduce(callback[, initialValue])
методаJavaScript 1.8
Сделал бы работу.
источник
[[1], [2,3]].reduce( (a,b) => a.concat(b), [] )
более сексуально[[1], [2,3]].reduce( (a,b) => a.concat(b))
Еще одно решение ECMAScript 6 в функциональном стиле:
Объявите функцию:
и использовать это:
Рассмотрим также встроенную функцию Array.prototype.flat () (предложение для ES6), доступную в последних выпусках современных браузеров. Благодаря @ (Константин Ван) и @ (Марк Эмери) упомянули это в комментариях.
flat
Функция имеет один параметр , определяющий ожидаемую глубину вложения массива, который равен1
по умолчанию.источник
RangeError: Maximum call stack size exceeded
источник
Обратите внимание: когда
Function.prototype.apply
([].concat.apply([], arrays)
) или оператор распространения ([].concat(...arrays)
) используется для выравнивания массива, оба могут вызвать переполнение стека для больших массивов, поскольку каждый аргумент функции хранится в стеке.Вот безопасная для стека реализация в функциональном стиле, которая сопоставляет самые важные требования друг с другом:
Как только вы привыкнете к функциям с маленькими стрелками в форме карри, композиции функций и функциям более высокого порядка, этот код будет выглядеть как проза. Программирование тогда просто состоит из объединения небольших строительных блоков, которые всегда работают как ожидалось, потому что они не содержат побочных эффектов.
источник
const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);
избавляет вас от визуального мусора и объясняет вашим товарищам по команде, почему вам нужны 3 дополнительные функции и некоторые вызовы функций.ES6 One Line Flatten
См. Lodash сглаживать , подчеркивание сглаживать (мелкие
true
)или
Протестировано с
ES6 One Line Deep Flatten
См. Lodash flattenDeep , подчеркивание flatten
Протестировано с
источник
Array.prototype.concat.apply([], arr)
потому что вы создаете дополнительный массив только для того, чтобы добраться доconcat
функции. Среды выполнения могут оптимизировать или не оптимизировать его при запуске, но доступ к функции в прототипе не выглядит уродливее, чем это уже есть в любом случае.Вы можете использовать
Array.flat()
сInfinity
любой глубиной вложенного массива.проверьте здесь для совместимости браузера
источник
Хаскельский подход
источник
ES6 способ:
Способ ES5 для
flatten
функции с ES3 откатом для N-кратных вложенных массивов:источник
Если у вас есть только массивы с 1 строковым элементом:
сделаю работу. Bt, что конкретно соответствует вашему примеру кода.
источник
['$4', ["$6"], ["$12"], ["$25"], ["$25", "$33", ['$45']]].join(',').split(',')
[1,4, [45, 't', ['e3', 6]]].toString().split(',')
---- или -----[1,4, [45, 't', ['e3', 6], false]].toString().split(',')
(Я просто пишу это как отдельный ответ, основанный на комментарии @danhbear.)
источник
Я рекомендую функцию генератора с эффективным использованием пространства :
При желании создайте массив сглаженных значений следующим образом:
источник
...
для перебора генератора.Я бы предпочел преобразовать весь массив, как есть, в строку, но, в отличие от других ответов, сделал бы это, используя,
JSON.stringify
а неtoString()
метод, который приводит к нежелательному результату.С этим
JSON.stringify
выводом все, что осталось, это удалить все скобки, еще раз обернуть результат начальными и конечными скобками и обработать результат, с помощьюJSON.parse
которого строка возвращается к «жизни».источник
["345", "2", "3,4", "2"]
вместо разделения каждого из этих значений на отдельные индексы"3,4"
.Вы также можете попробовать новый
Array.Flat()
метод. Это работает следующим образом:flat()
Метод создает новый массив со всеми элементами суб-массива объединяются в него рекурсивно до 1 слоя глубины (т.е. массивы внутри массивов)Если вы также хотите сгладить трехмерные или даже более многомерные массивы, вы просто вызываете метод flat несколько раз. Например (3 измерения):
Быть осторожен!
Array.Flat()
метод относительно новый. Старые браузеры, такие как ie, возможно, не реализовали этот метод. Если вы хотите, чтобы ваш код работал во всех браузерах, вам, возможно, придется перенести JS на более старую версию. Проверьте наличие MD-документов в Интернете на предмет текущей совместимости браузера.источник
Infinity
аргументом. Как это:arr.flat(Infinity)
Используя оператор распространения:
источник
Это не сложно, просто переберите массивы и объедините их:
источник
Похоже, это похоже на работу для рекурсии!
Код:
Применение:
источник
flatten(new Array(15000).fill([1]))
выкидываетUncaught RangeError: Maximum call stack size exceeded
и замораживает мои devTools на 10 секундЯ сделал это с помощью рекурсии и замыканий
источник
На днях я баловался с ES6 Generators и написал эту суть . Который содержит...
По сути, я создаю генератор, который зацикливается на исходном входном массиве. Если он находит массив, он использует оператор yield * в сочетании с рекурсией для постоянного выравнивания внутренних массивов. Если элемент не является массивом, он просто возвращает один элемент. Затем с помощью оператора ES6 Spread (он же оператор splat) я сплющил генератор в новый экземпляр массива.
Я не проверял производительность этого, но я полагаю, что это хороший простой пример использования генераторов и оператора yield *.
Но опять же, я был просто дураком, так что я уверен, что есть более эффективные способы сделать это.
источник
просто лучшее решение без лодаш
источник