Como achatar uma matriz multidimensional?

259

É 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().

Alix Axel
fonte
17
Por que evitar recursão?
JorenB
5
Dupe (principalmente) stackoverflow.com/questions/526556/… #
cletus
4
Você não pode fazer nada com todos os elementos de uma matriz arbitrariamente profunda sem recursão (você pode disfarçar isso como iteração, mas batata, potahto.) Se você quiser apenas evitar escrever o código de manipulação de recursão, use dk2.php.net/ manual / pt-br / function.array-walk-recursive.php com um retorno de chamada que adiciona o elemento a uma matriz disponível (use global, o parâmetro userdata, coloque tudo em uma classe e consulte $ this, etc.)
Michael Madsen
@JorenB: Eu gostaria que uma implementação pudesse ser arquivada.
Alix Axel
Ter um olhar para achatar função de NSPL . Você também pode especificar uma profundidade com ele.
Ihor Burlachenko 24/02

Respostas:

276

Você pode usar a SPL (Standard PHP Library) para "ocultar" a recursão.

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
foreach($it as $v) {
  echo $v, " ";
}

impressões

1 2 3 4 5 6 7 8 9 
VolkerK
fonte
351
Eu sou o único que pensa 'RecursiveIteratorIterator' é um nome bobo?
Nilamo 24/08/09
45
É mais "lógico" do que "cativante". Nem tudo pode ter um nome fantástico como JOGL, Knol ou Azure :-)
VolkerK
7
Isso não funcionará para matrizes vazias quando crianças. Eles serão devolvidos como pai.
hakre 22/10/11
45
iterator_to_array($it, false)evita a necessidade do foreach.
Alix Axel
3
Com base no que os outros apresentaram, pude criar este pequeno ajudante: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }Espero que isso ajude os outros.
Mike S.
296

A partir do PHP 5.3, a solução mais curta parece estar array_walk_recursive()com a nova sintaxe de fechamento:

function flatten(array $array) {
    $return = array();
    array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
    return $return;
}
muito php
fonte
33
se você quiser chaves, a função flatten (array $ array) {$ return = array (); array_walk_recursive ($ array, função ($ a, $ b) use (& $ return) {$ return [$ b] = $ a;}); return $ return; }
Brendon-Van-Heyzen
você pode reescrever isso para usar com o php 5.2?
Alex
2
@Alex infelizmente você precisa da usesintaxe para fazer este trabalho com array_walk_recursiveuma vez que não vai aceitar o opcional $userdataparâmetro por referência
Tim Seguine
1
Parece que funciona bem para essas matrizes -> ideone.com/DsmApP Mas não para essas - - ideone.com/5Kltva Ou sou eu?
Sebastian Piskorski
2
@Sebastian Piskorski é porque seus valores estão sendo tratados como chaves, assim que você introduz seu próprio par de chave => value em uma matriz, seus valores de matriz na primeira posição do índice são tratados como chaves sem valores, e porque as chaves têm para ser único, onde duas chaves correspondem, seus valores são adicionados à mesma chave. Uma solução simples seria classificar a matriz primeiro. Este é um comportamento inerente ao PHP.
Martyn Shutt
92

Solução para matriz bidimensional

Por favor tente isto:

$array  = your array

$result = call_user_func_array('array_merge', $array);

echo "<pre>";
print_r($result);

EDIT: 21-Ago-13

Aqui está a solução que funciona para um array multidimensional:

function array_flatten($array) {
    $return = array();
    foreach ($array as $key => $value) {
        if (is_array($value)){
            $return = array_merge($return, array_flatten($value));
        } else {
            $return[$key] = $value;
        }
    }

    return $return;
}

$array  = Your array

$result = array_flatten($array);

echo "<pre>";
print_r($result);

Ref: http://php.net/manual/en/function.call-user-func-array.php

Prasanth Bendra
fonte
Obrigado, o primeiro funcionou em uma matriz que eu estava recebendo do DOP, onde as outras soluções não.
JAL
7
Esta é uma péssima estratégia. 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.
cabra
O OP solicitou especificamente soluções não recursivas.
Elektra
Uau, cool 2d flattern! Mas para evitar aviso apenas usar$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov
bruh legal, mas você não tem por acaso uma contra-função array-deflatten?
FantomX1
64

No PHP 5.6 e superior, você pode nivelar matrizes bidimensionais array_mergeapós descompactar a matriz externa com o ...operador. O código é simples e claro.

array_merge(...$a);

Isso funciona com a coleção de matrizes associativas também.

$a = [[10, 20], [30, 40]];
$b = [["x" => "X", "y" => "Y"], ["p" => "P", "q" => "Q"]];

print_r(array_merge(...$a));
print_r(array_merge(...$b));

Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
)
Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

Mas não funciona quando a matriz externa possui chaves não numéricas. Nesse caso, você terá que ligar array_valuesprimeiro.

$c = ["a" => ["x" => "X", "y" => "Y"], "b" => ["p" => "P", "q" => "Q"]];
print_r(array_merge(...array_values($c)));

Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

Atualização: Com base no comentário de @MohamedGharib

Isso gerará um erro se a matriz externa estiver vazia, pois array_mergeseria chamada com zero argumentos. Isso pode ser evitado adicionando uma matriz vazia como o primeiro argumento.

array_merge([], ...$a);
Joyce Babu
fonte
1
Isso funciona apenas quando todos os elementos da matriz são uma matriz. Se a matriz compreender tipos mistos, como escalares, ocorrerá um erro.
Otheus 26/11/19
@Otheus Isso ocorre porque a solução acima não usa recursão. Como você disse, requer uma matriz de matriz. Mas no lado positivo, isso deve ser muito mais rápido que os outros métodos, pois não possui a sobrecarga adicional das chamadas de função.
Joyce Babu
2
Irá gerar um erro se a matriz externa estiver vazia, poderia ser evitável se combinada com uma matriz vaziaarray_merge([], ...$a);
Mohamed Gharib
@MohamedGharib Nice catch.
Joyce Babu
Se estiver usando matrizes associativas, você pode verificar esta solução stackoverflow.com/questions/40663687/…
alex
24

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 :.

function array_flatten(array $array)
{
    $flat = array(); // initialize return array
    $stack = array_values($array); // initialize stack
    while($stack) // process stack until done
    {
        $value = array_shift($stack);
        if (is_array($value)) // a value to further process
        {
            $stack = array_merge(array_values($value), $stack);
        }
        else // a value to take
        {
           $flat[] = $value;
        }
    }
    return $flat;
}

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: RecurisiveIteratorele usa recursão, portanto depende do que você realmente precisa. Também deve ser possível criar um iterador recursivo com base nas pilhas:

foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
    echo "** ($key) $value\n";
}

Demo

Eu não cheguei até agora, para implementar a pilha com base na RecursiveIteratorqual eu acho uma boa idéia.

hakre
fonte
+1 para a excelente função array_flatten. Eu tive que adicionar if(!empty($value)){$flat[] = $value}dentro da instrução else para evitar que o vazio fosse adicionado à matriz de resultados. Função impressionante!
Alex Sarnowski
19

Resposta direta e de uma linha .

function flatten_array(array $array)
{
    return iterator_to_array(
         new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
}

Uso:

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

print_r( flatten_array($array) );

Saída (em PsySH):

Array
(
    [name] => Allen Linatoc
    [age] => 21
    [0] => Call of Duty
    [1] => Titanfall
    [2] => Far Cry
)

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 :

Apenas para esclarecer, isso preserva as chaves (mesmo as numéricas) para que os valores que possuem a mesma chave sejam perdidos. Por exemplo, $array = ['a',['b','c']]torna-se Array ([0] => b, [1] => c ). O 'a'é perdido porque 'b'também tem uma chave de0

Citando a resposta de Svish :

Basta adicionar false como segundo parâmetro ($use_keys)à chamada iterator_to_array

Allen Linatoc
fonte
Apenas para esclarecer, isso preserva as chaves (mesmo as numéricas) para que os valores que possuem a mesma chave sejam perdidos. Por exemplo, $array = ['a',['b','c']]torna-se Array ([0] => b, [1] => c ). O 'a'é perdido porque 'b'também tem uma chave de 0.
Nigel Alderton
1
@NigelAlderton Basta adicionar falsecomo segundo parâmetro ( $use_keys) à iterator_to_arraychamada.
Svish
18

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.

function flatten($array) {
    if (!is_array($array)) {
        // nothing to do if it's not an array
        return array($array);
    }

    $result = array();
    foreach ($array as $value) {
        // explode the sub-array, and add the parts
        $result = array_merge($result, flatten($value));
    }

    return $result;
}


$arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
echo '<ul>';
foreach (flatten($arr) as $value) {
    echo '<li>', $value, '</li>';
}
echo '<ul>';

Resultado:

<ul><li>foo</li><li>nobody</li><li>expects</li><li>another</li><li>level</li><li>the</li><li>Spanish</li><li>Inquisition</li><li>bar</li><ul>
nilamo
fonte
1
Não tenho medo de recursão, só quero aprender outras maneiras de fazer o mesmo.
Alix Axel
13
+1 para esta recursão: esperançosamente, ao ver como não é complexo, seu medo de recursão se dissipará quando você ver como não é complexo.
Tiberiu-Ionuț Stan
1
OK, isso acabou comigo. Como é possível, essa resposta ("não tenho medo de recursão") é três anos e meio mais antiga (24 de agosto de 2009) do que a declaração inicial ("(...) seu medo de recursão se dissipará (... ) "), realizado em 5 de fevereiro de 13?
Trejder
18

Apenas pensei em apontar que essa é uma dobra, para que array_reduce possa ser usado:

array_reduce($my_array, 'array_merge', array());

EDIT: Observe que isso pode ser composto para nivelar qualquer número de níveis. Podemos fazer isso de várias maneiras:

// Reduces one level
$concat   = function($x) { return array_reduce($x, 'array_merge', array()); };

// We can compose $concat with itself $n times, then apply it to $x
// This can overflow the stack for large $n
$compose  = function($f, $g) {
    return function($x) use ($f, $g) { return $f($g($x)); };
};
$identity = function($x) { return $x; };
$flattenA = function($n) use ($compose, $identity, $concat) {
    return  function($x) use ($compose, $identity, $concat, $n) {
        return ($n === 0)? $x
                         : call_user_func(array_reduce(array_fill(0, $n, $concat),
                                                       $compose,
                                                       $identity),
                                          $x);
    };
};

// We can iteratively apply $concat to $x, $n times
$uncurriedFlip     = function($f) {
    return  function($a, $b) use ($f) {
        return $f($b, $a);
    };
};
$iterate  = function($f) use ($uncurriedFlip) {
    return  function($n) use ($uncurriedFlip, $f) {
    return  function($x) use ($uncurriedFlip, $f, $n) {
        return ($n === 0)? $x
                         : array_reduce(array_fill(0, $n, $f),
                                        $uncurriedFlip('call_user_func'),
                                        $x);
    }; };
};
$flattenB = $iterate($concat);

// Example usage:
$apply    = function($f, $x) {
    return $f($x);
};
$curriedFlip = function($f) {
    return  function($a) use ($f) {
    return  function($b) use ($f, $a) {
        return $f($b, $a);
    }; };
};

var_dump(
    array_map(
        call_user_func($curriedFlip($apply),
                       array(array(array('A', 'B', 'C'),
                                   array('D')),
                             array(array(),
                                   array('E')))),
        array($flattenA(2), $flattenB(2))));

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.

Warbo
fonte
Multi-dimensional! = Bidimensional.
Alix Axel
@atamur Isso funciona no PHP 5.3 ou superior. Como observado no changelog para array_reduce, $ inicial só poderia ser um inteiro antes de 5.3, em seguida, ele foi autorizado a ser "mistas" (ou seja, qualquer coisa que seu suporta a função de redução.)
Warbo
1
@AlixAxel Você está certo que multidimensional! = Bidimensional, mas isso pode ser composto para nivelar qualquer número de níveis. Uma boa consequência da composição de dobras é que ela obedece a um limite fixo; se eu tiver uma matriz aninhada em 5 níveis, eu posso foldem 4 níveis, ou fold . foldpara obter 3 níveis, ou fold . fold . foldpara 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.
Warbo 19/07/2013
Eu amo essa solução, para matrizes bidimensionais. Se encaixa perfeitamente.
Tom Auger
Concordo que sua definição de nível único é a melhor resposta, também é maravilhosamente elegante. No entanto, acho que você o nomeou incorretamente $concat, acho que deveria chamá-lo $flatten. array_mergeé o equivalente php de concat. Tentei ser array_concatadicionado como um alias para array_merge.
icc97
9

Nivela apenas as matrizes bidimensionais:

$arr = [1, 2, [3, 4]];
$arr = array_reduce($arr, function ($a, $b) {
     return array_merge($a, (array) $b);
}, []);

// Result: [1, 2, 3, 4]
artnikpro
fonte
5

Esta solução é não recursiva. Observe que a ordem dos elementos será um pouco mista.

function flatten($array) {
    $return = array();
    while(count($array)) {
        $value = array_shift($array);
        if(is_array($value))
            foreach($value as $sub)
                $array[] = $sub;
        else
            $return[] = $value;
    }
    return $return;
}
muito php
fonte
1
Idéia inteligente, mas há um bug. "$ array [] = $ value" não adiciona todos os elementos de $ value a $ array, apenas adiciona o próprio valor $. Se você executar esse código, ele fará um loop indefinidamente.
Todd Owen
Sim, shiftingo valor da matriz e anexá-lo novamente ao final não faz muito sentido. Eu acho que você queria array_merge()?
Deceze
4

Acredito que esta é a solução mais limpa sem o uso de mutações ou classes desconhecidas.

<?php

function flatten($array)
{
    return array_reduce($array, function($acc, $item){
        return array_merge($acc, is_array($item) ? flatten($item) : [$item]);
    }, []);
}


// usage
$array = [1, 2, [3, 4], [5, [6, 7]], 8, 9, 10];
print_r(flatten($array));
Dariush Alipour
fonte
3

Tente a seguinte função simples:

function _flatten_array($arr) {
  while ($arr) {
    list($key, $value) = each($arr); 
    is_array($value) ? $arr = $value : $out[$key] = $value;
    unset($arr[$key]);
  }
  return (array)$out;
}

Então a partir disso:

array (
  'und' => 
  array (
    'profiles' => 
    array (
      0 => 
      array (
        'commerce_customer_address' => 
        array (
          'und' => 
          array (
            0 => 
            array (
              'first_name' => 'First name',
              'last_name' => 'Last name',
              'thoroughfare' => 'Address 1',
              'premise' => 'Address 2',
              'locality' => 'Town/City',
              'administrative_area' => 'County',
              'postal_code' => 'Postcode',
            ),
          ),
        ),
      ),
    ),
  ),
)

você obtém:

array (
  'first_name' => 'First name',
  'last_name' => 'Last name',
  'thoroughfare' => 'Address 1',
  'premise' => 'Address 2',
  'locality' => 'Town/City',
  'administrative_area' => 'County',
  'postal_code' => 'Postcode',
)
kenorb
fonte
talvez você deve verificar a sua função ... parece que não funcionam como esperado
Emiliano
@Emiliano Tente fazer uma nova pergunta, talvez seus dados de entrada sejam diferentes, para que não funcionem no seu caso particular.
kenorb
temos poucos problemas, cada um deles é uma função obsoleta, você pode melhorar esse ponto em que você não era um cara novo aqui, você deve saber em segundo lugar se o seu código funcionar com uma versão específica do php e dizer em terceiro lugar se não funcionar com todos os dados
Emiliano
2

O truque é passar as matrizes de origem e destino por referência.

function flatten_array(&$arr, &$dst) {
    if(!isset($dst) || !is_array($dst)) {
        $dst = array();
    }
    if(!is_array($arr)) {
        $dst[] = $arr;
    } else {
        foreach($arr as &$subject) {
            flatten_array($subject, $dst);
        }
    }
}

$recursive = array('1', array('2','3',array('4',array('5','6')),'7',array(array(array('8'),'9'),'10')));
echo "Recursive: \r\n";
print_r($recursive);
$flat = null;
flatten_array($recursive, $flat);

echo "Flat: \r\n";
print_r($flat);

// If you change line 3 to $dst[] = &$arr; , you won't waste memory,
// since all you're doing is copying references, and imploding the array 
// into a string will be both memory efficient and fast:)

echo "String:\r\n";
echo implode(',',$flat);
Rick Garcia
fonte
2
/**
 * For merging values of a multidimensional array into one 
 *
 * $array = [
 *     0 => [
 *         0 => 'a1',
 *         1 => 'b1',
 *         2 => 'c1',
 *         3 => 'd1'
 *     ],
 *     1 => [
 *         0 => 'a2',
 *         1 => 'b2',
 *         2 => 'c2',
 *     ]
 * ];
 *
 * becomes : 
 *
 * $array = [
 *     0 => 'a1',
 *     1 => 'b1',
 *     2 => 'c1',
 *     3 => 'd1',
 *     4 => 'a2',
 *     5 => 'b2',
 *     6 => 'c2',
 *     
 * ]
 */
array_reduce
(
    $multiArray
    , function ($lastItem, $currentItem) {
        $lastItem = $lastItem ?: array();
        return array_merge($lastItem, array_values($currentItem));
    }
);

Fragmento de essência

Arsham
fonte
Isso parece suportar apenas matrizes bidimensionais.
Alix Axel
Você está certo. Não faz sentido usá-lo. Eu acho que a melhor solução é a resposta "muito php".
Arsham
2

Se você realmente não gosta de uma recursão ... tente mudar :)

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$o = [];
for ($i=0; $i<count($a); $i++) {
    if (is_array($a[$i])) {
        array_splice($a, $i+1, 0, $a[$i]);
    } else {
        $o[] = $a[$i];
    }
}

Nota: Nesta versão simples, isso não suporta chaves de matriz.

BurninLeo
fonte
Esta é uma abordagem interessante. em contraste com as outras soluções, ele edita a matriz original ($ a). Se você substituí-lo por um continue, é um pouco mais rápido.
pcarvalho
2

Que tal usar um gerador recursivo? https://ideone.com/d0TXCg

<?php

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

foreach (iterate($array) as $item) {
    var_dump($item);
};

function iterate($array)
{
    foreach ($array as $item) {
        if (is_array($item)) {
            yield from iterate($item);
        } else {
            yield $item;
        }
    }
}
Andriy
fonte
1

Para php 5.2

function flatten(array $array) {
    $result = array();

    if (is_array($array)) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                $result = array_merge($result, flatten($v));
            } else {
                $result[] = $v;
            }
        }
    }

    return $result;
}
Alexei T
fonte
Inclua algumas explicações nesta resposta somente de código.
Mckmackusa 19/09/19
1

Esta versão pode executar níveis profundos, rasos ou específicos de níveis:

/**
 * @param  array|object $array  array of mixed values to flatten
 * @param  int|boolean  $level  0:deep, 1:shallow, 2:2 levels, 3...
 * @return array
 */
function flatten($array, $level = 0) {
    $level = (int) $level;
    $result = array();
    foreach ($array as $i => $v) {
        if (0 <= $level && is_array($v)) {
            $v = flatten($v, $level > 1 ? $level - 1 : 0 - $level);
            $result = array_merge($result, $v);
        } elseif (is_int($i)) {
            $result[] = $v;
        } else {
            $result[$i] = $v; 
        }
    }
    return $result;
}
ryanve
fonte
Além de explicar o que esse snippet pode fazer, explique aos futuros pesquisadores como ele funciona.
Mckmackusa 19/09/19
1

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.

/**
 * Flattens a multi demensional array into a one dimensional
 * to be compatible with hidden html fields.
 *
 * @param array $array
 *  Array in the form:
 *  array(
 *    'a' => array(
 *      'b' => '1'
 *    )
 *  )
 *
 * @return array
 *  Array in the form:
 *  array(
 *    'a[b]' => 1,
 *  )
 */
function flatten_array($array) {
  // Continue until $array is a one-dimensional array.
  $continue = TRUE;
  while ($continue) {
    $continue = FALSE;

    // Walk through top and second level of $array and move 
    // all values in the second level up one level.
    foreach ($array as $key => $value) {
      if (is_array($value)) {
        // Second level found, therefore continue.
        $continue = TRUE;

        // Move each value a level up.
        foreach ($value as $child_key => $child_value) {
          $array[$key . '[' . $child_key . ']'] = $child_value;
        }

        // Remove second level array from top level.
        unset($array[$key]);
      }
    }
  }

  return $array;
}
Gellweiler
fonte
1

Isso pode ser alcançado usando array_walk_recursive

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
array_walk_recursive($a, function($v) use (&$r){$r[]=$v;});
print_r($r);

Exemplo de trabalho: - https://3v4l.org/FpIrG

Rakesh Jakhar
fonte
0

Esta é a minha solução, usando uma referência:

function arrayFlatten($array_in, &$array_out){

    if(is_array($array_in)){
        foreach ($array_in as $element){
               arrayFlatten($element, $array_out);
        }
    }
    else{
        $array_out[] = $array_in; 
    }
}

$arr1 = array('1', '2', array(array(array('3'), '4', '5')), array(array('6')));

arrayFlatten($arr1, $arr2);

echo "<pre>";
print_r($arr2);
echo "</pre>";
Martyn Shutt
fonte
Inclua algumas explicações sobre como o seu snippet funciona e por que é uma boa ideia. As respostas somente de código são de baixo valor no StackOverflow, porque fazem um trabalho ruim de educar / capacitar o OP e futuros pesquisadores. Lembre-se, nunca estamos falando SOMENTE com o OP; páginas antigas são usadas para fechar novas páginas; portanto, as páginas precisam ser informativas o suficiente para resolver problemas para futuros solicitantes também.
Mickmackusa 19/09/19
0
<?php
//recursive solution

//test array
$nested_array = [[1,2,[3]],4,[5],[[[6,[7=>[7,8,9,10]]]]]];

/*-----------------------------------------
function call and return result to an array
------------------------------------------*/
$index_count = 1;
$flatered_array = array();
$flatered_array = flat_array($nested_array, $index_count);

/*-----------------------------------------
Print Result
-----------------------------------------*/
echo "<pre>";
print_r($flatered_array);


/*-----------------------------------------
function to flaten an array 
-----------------------------------------*/
function flat_array($nested_array, & $index_count, & $flatered_array) {

  foreach($nested_array AS $key=>$val) {
      if(is_array($val)) {
        flat_array($val, $index_count, $flatered_array);
      }
      else {
        $flatered_array[$index_count] = $val;
        ++$index_count;
      }      
  }

return $flatered_array;
}
?>
Furqan Freed
fonte
0

Aqui está uma abordagem simplista:

$My_Array = array(1,2,array(3,4, array(5,6,7), 8), 9);

function checkArray($value) {
    foreach ($value as $var) {
        if ( is_array($var) ) {
            checkArray($var);
        } else {
            echo $var;
        }
    }
}

checkArray($My_Array);
Jack
fonte
0

Quem procura uma solução realmente limpa para isso; aqui está uma opção:

$test_array = array(
    array('test' => 0, 0, 0, 0),
    array(0, 0, 'merp' => array('herp' => 'derp'), 0),
    array(0, 0, 0, 0),
    array(0, 0, 0, 0)
);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($test_array));
var_dump( iterator_to_array($it, false) ) ; 

Impressões

 0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0
Lewis
fonte
0

Apenas postando outra solução)

function flatMultidimensionalArray(array &$_arr): array
{
    $result = [];
    \array_walk_recursive($_arr, static function (&$value, &$key) use (&$result) {
        $result[$key] = $value;
    });

    return $result;
}
James Bond
fonte
0

Se você deseja manter também suas chaves, essa é a solução.

function reduce(array $array) {
    $return = array();
    array_walk_recursive($array, function($value, $key) use (&$return) { $return[$key] = $value; });
    return $return;
}

Infelizmente, ele gera apenas matrizes aninhadas finais, sem chaves do meio. Então, para o seguinte exemplo:

$array = array(
    'sweet' => array(
        'a' => 'apple',
        'b' => 'banana'),
    'sour' => 'lemon'); 
print_r(flatten($fruits));

A saída é:

Array
(
    [a] => apple
    [b] => banana
    [sour] => lemon
)
Tajni
fonte
-1

Eu precisava representar a matriz multidimensional do PHP no formato de entrada HTML.

$test = [
    'a' => [
        'b' => [
            'c' => ['a', 'b']
        ]
    ],
    'b' => 'c',
    'c' => [
        'd' => 'e'
    ]
];

$flatten = function ($input, $parent = []) use (&$flatten) {
    $return = [];

    foreach ($input as $k => $v) {
        if (is_array($v)) {
            $return = array_merge($return, $flatten($v, array_merge($parent, [$k])));
        } else {
            if ($parent) {
                $key = implode('][', $parent) . '][' . $k . ']';

                if (substr_count($key, ']') != substr_count($key, '[')) {
                    $key = preg_replace('/\]/', '', $key, 1);
                }
            } else {
                $key = $k;
            }           

            $return[$key] = $v;
        }
    }

    return $return;
};

die(var_dump( $flatten($test) ));

array(4) {
  ["a[b][c][0]"]=>
  string(1) "a"
  ["a[b][c][1]"]=>
  string(1) "b"
  ["b"]=>
  string(1) "c"
  ["c[d]"]=>
  string(1) "e"
}
Gajus
fonte
@AlixAxel Como esse comentário é relativo? Mensagem errada ..?
Gajus
Não. Pensei que era muito parecido com o que você está fazendo e decidi compartilhá-lo, acho que a única diferença é que minha representação também é válida em PHP - do formulário $var['a']['b']['c'][0] = 'a'; ....
Alix Axel
Eu intencionalmente precisava de saída HTML. Embora obrigado por compartilhar.
Gajus
1
Eu sinto que esta é a resposta certa para a pergunta errada. Ao responder, tente responder à pergunta conforme ela é solicitada - caso contrário, as páginas podem sair da questão principal e deixar futuros pesquisadores confusos.
Mckmackusa 19/09/19
-1

Se você possui uma matriz de objetos e deseja nivelá-la com um nó, basta usar esta função:

function objectArray_flatten($array,$childField) {
    $result = array();
    foreach ($array as $node)
    {
        $result[] = $node;
        if(isset($node->$childField))
        {
            $result = array_merge(
                $result, 
                objectArray_flatten($node->$childField,$childField)
            );
            unset($node->$childField);
        }

    }
    return $result;
}
حسین شکرزاده
fonte