Как инвертировать многомерный массив в PHP - PullRequest
3 голосов
/ 19 февраля 2010

Какой самый простой способ инвертировать многомерный массив. Под инвертированием я имею в виду аналогично array_flip.

* 1003 например *

[0][5][var_name] = data
[0][3][var_name2] = data2
[1][var_name3] = data3
[0][1][4][var_name4] = data4

инвертировано будет:

[var_name][0][5] = data
[var_name2][0][3] = data2
[var_name3][1] = data3
[var_name4][0][1][4] = data4

Есть идеи?

Ответы [ 2 ]

1 голос
/ 19 февраля 2010

Вы можете сохранить список ключей всех предков, и когда вы нажмете «лист», используйте этот список для создания «перевернутой» версии.

<?php
$data = array(
  0=>array(
    5=>array('var_name' => 'data'),
    3=>array('var_name2' => 'data2'),
    1=>array(4=>array('var_name4'=>'data4'))
  ),
  1=>array('var_name3'=>'data3')
);

$result = array();
foo($data, $result);

($result['var_name'][0][5] === 'data') or die('1');
($result['var_name2'][0][3] === 'data2') or die('2');
($result['var_name3'][1] === 'data3') or die('3');
($result['var_name4'][0][1][4] === 'data4') or die('4');
echo 'ok';


function foo(array $a, array &$target, $stack=array()) {
  foreach($a as $key=>$value) {
    if ( is_array($value) ) {
      array_push($stack, $key);
      foo($value, $target, $stack);
      array_pop($stack);
    }
    else {
      $target[$key] = array();
      $tmp = &$target[$key];
      foreach( $stack as $s ) { // now it's not so stack-ish anymore :-S
        $tmp[$s] = array();
        $tmp = &$tmp[$s];
      }
      $tmp = $value;
    }
  }
}
1 голос
/ 19 февраля 2010

Я не мог придумать простой способ сделать это. Поэтому я написал действительно сложный способ сделать это. А именно:

  1. Возьмите многомерный массив и сведите его в список ключей и значений.
  2. Обратный ход клавиш.
  3. Разблокировать список, чтобы получить инвертированный многомерный массив.

код

<?php
function print_entries($array, $prekeys = array())
{
    foreach ($array as $key => $value)
    {
        $keys = array_merge($prekeys, array($key));

        if (is_array($value))
            print_entries($value, $keys);
        else
            echo '[' . implode('][', $keys) . "] = $value\n";
    }
}

function flatten_array($array)
{
    $entries = array();

    foreach ($array as $key => $value)
    {
        if (is_array($value))
        {
            foreach (flatten_array($value) as $subentry)
            {
                $subkeys  = $subentry[0];
                $subvalue = $subentry[1];

                $entries[] = array(array_merge(array($key), $subkeys), $subvalue);
            }
        }
        else
            $entries[] = array(array($key), $value);
    }

    return $entries;
}

function unflatten_array($entries)
{
    $array = array();

    foreach ($entries as $entry)
    {
        $keys  = $entry[0];
        $value = $entry[1];

        $subarray = &$array;

        foreach ($keys as $i => $key)
        {
            if ($i < count($keys) - 1)
            {
                if (!isset($subarray[$key]))
                    $subarray[$key] = array();

                $subarray = &$subarray[$key];
            }
            else
                $subarray[$key] = $value;
        }
    }

    return $array;
}

function invert_array($array)
{
    $entries = flatten_array($array);

    foreach ($entries as &$entry)
        $entry[0] = array_reverse($entry[0]);

    return unflatten_array($entries);
}

$array = array
(
    0 => array
    (
        5 => array('var_name' => 'data'),
        3 => array('var_name2' => 'data2'),
        1 => array(4 => array('var_name4' => 'data4'))
    ),

    1 => array(0 => array('var_name' => 'data3'))
);

print_entries($array);
echo "\n";
print_entries(invert_array($array));
?>

выход

[0][5][var_name] = data
[0][3][var_name2] = data2
[0][1][4][var_name4] = data4
[1][0][var_name] = data3

[var_name][5][0] = data
[var_name2][3][0] = data2
[var_name4][4][1][0] = data4
[var_name][0][1] = data3

Редактировать: Теперь я заметил, что вы не меняете клавиши, а просто перемещаете часть var_name от конца к передней части и оставляете числовые индексы в покое. Достаточно просто изменить строку в flatten_array, где я звоню array_reverse, чтобы переупорядочить ключи другим способом. Базовая логика сглаживания / разглаживания не нуждается в изменении. Я оставляю это как упражнение для читателя. : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...