É possível, em PHP, achatar uma matriz dimensional (bi / multi) sem usar recursão ou referências?
Estou interessado apenas nos valores para que as chaves possam ser ignoradas, estou pensando nas linhas de array_map()
e array_values()
.
php
arrays
multidimensional-array
flatten
Alix Axel
fonte
fonte
Respostas:
Você pode usar a SPL (Standard PHP Library) para "ocultar" a recursão.
impressões
fonte
iterator_to_array($it, false)
evita a necessidade do foreach.function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }
Espero que isso ajude os outros.A partir do PHP 5.3, a solução mais curta parece estar
array_walk_recursive()
com a nova sintaxe de fechamento:fonte
use
sintaxe para fazer este trabalho comarray_walk_recursive
uma vez que não vai aceitar o opcional$userdata
parâmetro por referênciaSolução para matriz bidimensional
Por favor tente isto:
EDIT: 21-Ago-13
Aqui está a solução que funciona para um array multidimensional:
Ref: http://php.net/manual/en/function.call-user-func-array.php
fonte
call_user_func_array('array_merge', [])
(observe a matriz vazia) retorna nulo e dispara um erro de aviso de php. É uma solução inteligente se você souber que sua matriz não estará vazia, mas essa não é uma suposição comum que muitos podem fazer.$result = $array ?call_user_func_array('array_merge', $array) : [];
No PHP 5.6 e superior, você pode nivelar matrizes bidimensionais
array_merge
após descompactar a matriz externa com o...
operador. O código é simples e claro.Isso funciona com a coleção de matrizes associativas também.
Mas não funciona quando a matriz externa possui chaves não numéricas. Nesse caso, você terá que ligar
array_values
primeiro.Atualização: Com base no comentário de @MohamedGharib
Isso gerará um erro se a matriz externa estiver vazia, pois
array_merge
seria chamada com zero argumentos. Isso pode ser evitado adicionando uma matriz vazia como o primeiro argumento.fonte
array_merge([], ...$a);
Para achatar sem recursão (como você pediu), você pode usar uma pilha . Naturalmente, você pode colocar isso em uma função própria
array_flatten
. A seguir está uma versão que funciona sem teclas :.Os elementos são processados em sua ordem. Como os subelementos serão movidos para o topo da pilha, eles serão processados a seguir.
Também é possível levar em consideração as chaves; no entanto, você precisará de uma estratégia diferente para lidar com a pilha. Isso é necessário porque você precisa lidar com possíveis chaves duplicadas nas sub-matrizes. Uma resposta semelhante em uma pergunta relacionada: PHP Percorra uma matriz multidimensional enquanto preserva chaves
Não tenho certeza específica, mas eu já havia testado isso no passado:
RecurisiveIterator
ele usa recursão, portanto depende do que você realmente precisa. Também deve ser possível criar um iterador recursivo com base nas pilhas:Demo
Eu não cheguei até agora, para implementar a pilha com base na
RecursiveIterator
qual eu acho uma boa idéia.fonte
if(!empty($value)){$flat[] = $value}
dentro da instrução else para evitar que o vazio fosse adicionado à matriz de resultados. Função impressionante!Resposta direta e de uma linha .
Uso:
Saída (em PsySH):
Agora cabe a você decidir como vai lidar com as chaves. Felicidades
EDIT (2017-03-01)
Citando a preocupação / questão de Nigel Alderton :
Citando a resposta de Svish :
fonte
$array = ['a',['b','c']]
torna-seArray ([0] => b, [1] => c )
. O'a'
é perdido porque'b'
também tem uma chave de0
.false
como segundo parâmetro ($use_keys
) àiterator_to_array
chamada.Usa recursão. Esperemos que, ao ver como não é complexo, seu medo de recursão se dissipará quando você ver como não é complexo.
Resultado:
fonte
Apenas pensei em apontar que essa é uma dobra, para que array_reduce possa ser usado:
EDIT: Observe que isso pode ser composto para nivelar qualquer número de níveis. Podemos fazer isso de várias maneiras:
Obviamente, também poderíamos usar loops, mas a pergunta solicita uma função combinadora ao longo das linhas de array_map ou array_values.
fonte
fold
em 4 níveis, oufold . fold
para obter 3 níveis, oufold . fold . fold
para obter 2 níveis, etc. Isso também evita que os erros sejam ocultados; por exemplo. se eu quiser achatar uma matriz 5D, mas receber uma matriz 4D, o erro será acionado imediatamente.$concat
, acho que deveria chamá-lo$flatten
.array_merge
é o equivalente php de concat. Tentei serarray_concat
adicionado como um alias paraarray_merge
.Nivela apenas as matrizes bidimensionais:
fonte
Esta solução é não recursiva. Observe que a ordem dos elementos será um pouco mista.
fonte
shifting
o valor da matriz e anexá-lo novamente ao final não faz muito sentido. Eu acho que você queriaarray_merge()
?Acredito que esta é a solução mais limpa sem o uso de mutações ou classes desconhecidas.
fonte
Tente a seguinte função simples:
Então a partir disso:
você obtém:
fonte
O truque é passar as matrizes de origem e destino por referência.
fonte
Fragmento de essência
fonte
Você pode fazer isso com guloseimas ouzo :
Veja: Aqui
fonte
Se você realmente não gosta de uma recursão ... tente mudar :)
Nota: Nesta versão simples, isso não suporta chaves de matriz.
fonte
continue
, é um pouco mais rápido.Que tal usar um gerador recursivo? https://ideone.com/d0TXCg
fonte
Para php 5.2
fonte
Esta versão pode executar níveis profundos, rasos ou específicos de níveis:
fonte
Porque o código aqui parece assustador. Aqui está uma função que também converterá uma matriz multidimensional em sintaxe compatível com a forma html, mas que é mais fácil de ler.
fonte
Isso pode ser alcançado usando
array_walk_recursive
Exemplo de trabalho: - https://3v4l.org/FpIrG
fonte
Esta é a minha solução, usando uma referência:
fonte
fonte
Aqui está uma abordagem simplista:
fonte
Quem procura uma solução realmente limpa para isso; aqui está uma opção:
Impressões
fonte
Apenas postando outra solução)
fonte
Se você deseja manter também suas chaves, essa é a solução.
Infelizmente, ele gera apenas matrizes aninhadas finais, sem chaves do meio. Então, para o seguinte exemplo:
A saída é:
fonte
Eu precisava representar a matriz multidimensional do PHP no formato de entrada HTML.
fonte
$var['a']['b']['c'][0] = 'a'; ...
.Se você possui uma matriz de objetos e deseja nivelá-la com um nó, basta usar esta função:
fonte