Tengo una matriz de JavaScript como:
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
¿Cómo haría para fusionar las matrices internas separadas en una como:
["$6", "$12", "$25", ...]
javascript
arrays
flatten
Andy
fuente
fuente

reduce+concatson O ((N ^ 2) / 2) donde como respuesta aceptada (solo una llamada aconcat) sería como máximo O (N * 2) en un navegador defectuoso y O (N) en un bueno Además, la solución de Denys está optimizada para la pregunta real y hasta 2 veces más rápido que la únicaconcat. Para lareducegente, es divertido sentirse bien escribiendo un código pequeño, pero por ejemplo, si la matriz tuviera 1000 subarreglos de un elemento, todas las soluciones reduce + concat estarían haciendo 500500 operaciones, mientras que el concat único o el bucle simple harían 1000 operaciones.[].concat(...array)array.flat(Infinity)dóndeInfinityestá la profundidad máxima para aplanar?Respuestas:
Puede usar
concatpara fusionar matrices:Usar el
applymétodo deconcatsolo tomará el segundo parámetro como una matriz, por lo que la última línea es idéntica a esta:También existe el
Array.prototype.flat()método (introducido en ES2019) que podría usar para aplanar las matrices, aunque solo está disponible en Node.js a partir de la versión 11, y no está disponible en absoluto en Internet Explorer .fuente
concatno modifica la matriz de origen, por lo que lamergedmatriz permanecerá vacía después de la llamada aconcat. Mejor decir algo como:merged = merged.concat.apply(merged, arrays);var merged = [].concat.apply([], arrays);parece funcionar bien para obtenerlo en una línea. editar: como ya muestra la respuesta de Nikita.Array.prototype.concat.apply([], arrays).var merged = [].concat(...arrays)Aquí hay una función corta que usa algunos de los métodos de matriz JavaScript más nuevos para aplanar una matriz n-dimensional.
Uso:
fuente
flaten la primera llamada a la función anónima pasadareduce. Si no se especifica, entonces la primera llamada parareducevincular el primer valor fuera de la matrizflat, lo que eventualmente resultaría1vinculado aflatambos ejemplos.1.concatNo es una función.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), []);Hay un método confusamente oculto, que construye una nueva matriz sin mutar la original:
fuente
[].concat([[1],[2,3],[4]]...)[[1],[2,3],[4]]como resultado. La solución que da @Nikita es correcta tanto para CoffeeScript como para JS.[].concat([1],[2,3],[4],...)....son de código real, no algunos puntos suspensivos.Se puede hacer mejor con la función de reducción de JavaScript.
O con ES2015:
js-violín
Documentos de Mozilla
fuente
[]y no se necesitan más validaciones.arrays.reduce((flatten, arr) => [...flatten, ...arr])Hay un nuevo método nativo llamado plano para hacer esto exactamente.
(A fines de 2019,
flatahora se publica en el estándar ECMA 2019, ycore-js@3(la biblioteca de babel) lo incluye en su biblioteca de polyfill )fuente
La mayoría de las respuestas aquí no funcionan en grandes matrices (por ejemplo, 200 000 elementos), e incluso si lo hacen, son lentas. La respuesta de polkovnikov.ph tiene el mejor rendimiento, pero no funciona para el aplanamiento profundo.
Aquí está la solución más rápida, que también funciona en matrices con múltiples niveles de anidamiento :
Ejemplos
Enormes matrices
Maneja grandes matrices muy bien. En mi máquina, este código tarda unos 14 ms en ejecutarse.
Matrices anidadas
Funciona con matrices anidadas. Este código produce
[1, 1, 1, 1, 1, 1, 1, 1].Matrices con diferentes niveles de anidamiento
No tiene ningún problema al aplanar matrices como esta.
fuente
RangeError: Maximum call stack size exceeded). Para una matriz de 20 000 elementos, tarda de 2 a 5 milisegundos.Actualización: resultó que esta solución no funciona con matrices grandes. Si está buscando una solución mejor y más rápida, consulte esta respuesta .
Simplemente se expande
arry se lo pasa como argumentos aconcat(), lo que combina todas las matrices en una sola. Es equivalente a[].concat.apply([], arr).También puede probar esto para el aplanamiento profundo:
Ver demo en JSBin .
Referencias para los elementos de ECMAScript 6 utilizados en esta respuesta:
Nota al margen: los métodos como
find()y las funciones de flecha no son compatibles con todos los navegadores, pero eso no significa que no pueda usar estas funciones en este momento. Simplemente use Babel : transforma el código ES6 en ES5.fuente
applyde esta manera, eliminé mis comentarios de los suyos. Todavía pienso utilizandoapply/ propagan de esta manera es mal consejo, pero ya nadie le importa ...const flatten = arr => [].concat(...arr)Puedes usar el subrayado :
fuente
trueel segundo argumento .Los procedimientos genéricos significan que no tenemos que reescribir la complejidad cada vez que necesitamos utilizar un comportamiento específico.
concatMap(oflatMap) es exactamente lo que necesitamos en esta situación.previsión
Y sí, lo has adivinado correctamente, solo se aplana un nivel, que es exactamente cómo debería funcionar
Imagina un conjunto de datos como este
Ok, ahora digamos que queremos imprimir una lista que muestre a todos los jugadores que participarán en
game...Si nuestro
flattenprocedimiento también aplanara las matrices anidadas, terminaríamos con este resultado basura ...rodando profundo, bebé
Eso no quiere decir que a veces no quieras aplanar matrices anidadas, solo que ese no debería ser el comportamiento predeterminado.
Podemos hacer un
deepFlattenprocedimiento con facilidad ...Allí. Ahora tiene una herramienta para cada trabajo: una para aplastar un nivel de anidamiento
flatteny otra para eliminar todo el anidamientodeepFlatten.Tal vez puedas llamarlo
obliterateonukesi no te gusta el nombredeepFlatten.¡No repitas dos veces!
Por supuesto, las implementaciones anteriores son inteligentes y concisas, pero el uso de un
.mapseguido de un llamado a.reducesignifica que en realidad estamos haciendo más iteraciones de las necesariasUsar un combinador de confianza al que llamo
mapReduceayuda a mantener las iteraciones en un mínimo; toma una función de mapeom :: a -> b, una función reductorar :: (b,a) ->by devuelve una nueva función reductora: este combinador está en el corazón de los transductores ; si te interesa, he escrito otras respuestas sobre ellosfuente
concatsí no volar la pila, única...yapplyhace (junto con matrices muy grandes). No lo vi Me siento terrible en este momento.concaten Javascript tiene un significado diferente que en Haskell. Haskell'sconcat([[a]] -> [a]) se llamaríaflattenen Javascript y se implementaría comofoldr (++) [](Javascript:foldr(concat) ([])asumiendo funciones currificadas). Javascriptconcates un agregado extraño ((++)en Haskell), que puede manejar ambos[a] -> [a] -> [a]ya -> [a] -> [a].flatMap, porque eso es exactamente lo queconcatMapes: labindinstancia de lalistmónada.concatpMapse implementa comofoldr ((++) . f) []. Traducido en Javascript:const flatMap = f => foldr(comp(concat) (f)) ([]). Por supuesto, esto es similar a su implementación sincomp.Una solución para el caso más general, cuando puede tener algunos elementos que no son de matriz en su matriz.
fuente
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)o estoflattenArrayOfArrays(arr, [1,[3]]);: esos segundos argumentos se agregan a la salida.rrealmente concatene los resultados de la recursividad.Para aplanar una matriz de matrices de un solo elemento, no necesita importar una biblioteca, un bucle simple es la solución más simple y más eficiente :
Para los votantes negativos: lea la pregunta, no haga votos negativos porque no se adapta a su problema muy diferente. Esta solución es tanto la más rápida como la más simple para la pregunta formulada.
fuente
['foo', ['bar']]a['f', 'bar'].¿Qué pasa con el uso del
reduce(callback[, initialValue])método deJavaScript 1.8Haría el trabajo
fuente
[[1], [2,3]].reduce( (a,b) => a.concat(b), [] )Es más sexy.[[1], [2,3]].reduce( (a,b) => a.concat(b))Otra solución ECMAScript 6 en estilo funcional:
Declarar una función:
y úsalo:
Considere también una función nativa Array.prototype.flat () (propuesta para ES6) disponible en las últimas versiones de los navegadores modernos. Gracias a @ (Константин Ван) y @ (Mark Amery) lo mencionaron en los comentarios.
La
flatfunción tiene un parámetro, que especifica la profundidad esperada de la anidación de la matriz, que es igual1por defecto.fuente
RangeError: Maximum call stack size exceededfuente
Tenga en cuenta: cuando se usa
Function.prototype.apply([].concat.apply([], arrays)) o el operador de propagación ([].concat(...arrays)) para aplanar una matriz, ambos pueden causar desbordamientos de la pila para matrices grandes, porque cada argumento de una función se almacena en la pila.Aquí hay una implementación segura para la pila en un estilo funcional que sopesa los requisitos más importantes entre sí:
Tan pronto como se acostumbre a las funciones de flecha pequeña en forma de curry, composición de funciones y funciones de orden superior, este código se lee como prosa. La programación consiste simplemente en juntar pequeños bloques de construcción que siempre funcionan como se espera, porque no contienen ningún efecto secundario.
fuente
const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);ahorra basura visual y explica a sus compañeros de equipo por qué necesita 3 funciones adicionales y algunas llamadas a funciones también.ES6 One Line Flatten
Ver aplanar lodash , subrayar aplanar (poco profundo
true)o
Probado con
ES6 One Line Deep Flatten
Ver aplanar lodash Profundo , subrayar aplanar
Probado con
fuente
Array.prototype.concat.apply([], arr)porque crea una matriz adicional solo para acceder a laconcatfunción. Los tiempos de ejecución pueden o no optimizarlo cuando lo ejecutan, pero acceder a la función en el prototipo no parece más feo de lo que ya es en cualquier caso.Puede usar
Array.flat()conInfinitycualquier profundidad de matriz anidada.verifique aquí la compatibilidad del navegador
fuente
Un enfoque Haskellesque
fuente
Manera ES6:
Forma ES5 para la
flattenfunción con el respaldo ES3 para matrices anidadas N veces:fuente
Si solo tiene matrices con 1 elemento de cadena:
Hará el trabajo. Bt que coincide específicamente con su ejemplo de código.
fuente
['$4', ["$6"], ["$12"], ["$25"], ["$25", "$33", ['$45']]].join(',').split(',')[1,4, [45, 't', ['e3', 6]]].toString().split(',')---- o -----[1,4, [45, 't', ['e3', 6], false]].toString().split(',')(Solo estoy escribiendo esto como una respuesta separada, basada en el comentario de @danhbear).
fuente
Recomiendo una función de generador de espacio eficiente :
Si lo desea, cree una matriz de valores aplanados de la siguiente manera:
fuente
...para iterar a través del generador.Prefiero transformar toda la matriz, tal cual, en una cadena, pero a diferencia de otras respuestas, lo haría usando
JSON.stringifyy no eltoString()método, que produce un resultado no deseado.Con esa
JSON.stringifysalida, todo lo que queda es eliminar todos los corchetes, ajustar el resultado con los corchetes de inicio y finalización una vez más, y servir el resultado con elJSON.parseque la cadena vuelve a la "vida".fuente
["345", "2", "3,4", "2"]lugar de separar cada uno de esos valores para separar los índices"3,4".También puedes probar el nuevo
Array.Flat()método. Funciona de la siguiente manera:El
flat()método crea una nueva matriz con todos los elementos de la sub-matriz concatenados recursivamente hasta la capa de profundidad 1 (es decir, matrices dentro de las matrices)Si también desea aplanar matrices tridimensionales o incluso de dimensiones superiores, simplemente llame al método plano varias veces. Por ejemplo (3 dimensiones):
¡Ten cuidado!
Array.Flat()El método es relativamente nuevo. Los navegadores más antiguos como ie podrían no haber implementado el método. Si desea que el código funcione en todos los navegadores, es posible que deba transpilar su JS a una versión anterior. Verifique los documentos web de MD para ver la compatibilidad actual del navegador.fuente
Infinityargumento. Así:arr.flat(Infinity)Usando el operador de propagación:
fuente
Eso no es difícil, solo itera sobre las matrices y únelas:
fuente
¡Parece que esto parece un trabajo para RECURSION!
Código:
Uso:
fuente
flatten(new Array(15000).fill([1]))lanzaUncaught RangeError: Maximum call stack size exceededy congela mis devTools por 10 segundosLo hice usando recursividad y cierres
fuente
Estaba haciendo el tonto con los generadores ES6 el otro día y escribí esta esencia . Que contiene...
Básicamente, estoy creando un generador que recorre la matriz de entrada original, si encuentra una matriz, utiliza el operador de rendimiento * en combinación con la recursión para aplanar continuamente las matrices internas. Si el artículo no es una matriz, solo produce el artículo individual. Luego, utilizando el operador ES6 Spread (también conocido como operador splat), aplané el generador en una nueva instancia de matriz.
No he probado el rendimiento de esto, pero creo que es un buen ejemplo simple del uso de generadores y el operador de rendimiento *.
Pero nuevamente, solo estaba haciendo el ridículo, así que estoy seguro de que hay formas más efectivas de hacer esto.
fuente
la mejor solución sin lodash
fuente