80

PHP で多次元配列をどのように 90 度反転 (転置) しますか? 例えば:

// Start with this array
$foo = array(
    'a' => array(
       1 => 'a1',
       2 => 'a2',
       3 => 'a3' 
    ),
    'b' => array(
       1 => 'b1',
       2 => 'b2',
       3 => 'b3' 
    ),
    'c' => array(
       1 => 'c1',
       2 => 'c2',
       3 => 'c3' 
    )
);

$bar = flipDiagonally($foo); // Mystery function
var_dump($bar[2]);

// Desired output:
array(3) {
  ["a"]=>
  string(2) "a2"
  ["b"]=>
  string(2) "b2"
  ["c"]=>
  string(2) "c2"
}

どのように実装しflipDiagonally()ますか?

編集:これは宿題ではありません。最も明白なルートよりも創造的なソリューションを持っている SOer がいるかどうかを確認したいだけです。しかし、この問題が簡単すぎると不満を言う人が何人かいたので、n 次元配列で機能するより一般的な解決策はどうでしょうか?

つまり、次のような関数をどのように記述しますか。

$foo[j][k][...][x][y][z] = $bar[z][k][...][x][y][j]

for loops?(ps。この場合、12 個のネストが最適なソリューションではないと思います。)

4

14 に答える 14

264
function transpose($array) {
    array_unshift($array, null);
    return call_user_func_array('array_map', $array);
}

または、PHP 5.6 以降を使用している場合:

function transpose($array) {
    return array_map(null, ...$array);
}
于 2010-08-06T12:22:47.707 に答える
74

2ループ付き。

function flipDiagonally($arr) {
    $out = array();
    foreach ($arr as $key => $subarr) {
        foreach ($subarr as $subkey => $subvalue) {
            $out[$subkey][$key] = $subvalue;
        }
    }
    return $out;
}
于 2009-04-28T10:39:03.627 に答える
8

配列の転置(列が行になり、行が列になる)について言及していると思います。

これはあなたのためにそれを行う関数です(ソース)

function array_transpose($array, $selectKey = false) {
    if (!is_array($array)) return false;
    $return = array();
    foreach($array as $key => $value) {
        if (!is_array($value)) return $array;
        if ($selectKey) {
            if (isset($value[$selectKey])) $return[] = $value[$selectKey];
        } else {
            foreach ($value as $key2 => $value2) {
                $return[$key2][$key] = $value2;
            }
        }
    }
    return $return;
} 
于 2009-04-28T10:47:00.583 に答える
3

N 次元配列の転置:

function transpose($array, &$out, $indices = array())
{
    if (is_array($array))
    {
        foreach ($array as $key => $val)
        {
            //push onto the stack of indices
            $temp = $indices;
            $temp[] = $key;
            transpose($val, $out, $temp);
        }
    }
    else
    {
        //go through the stack in reverse - make the new array
        $ref = &$out;
        foreach (array_reverse($indices) as $idx)
            $ref = &$ref[$idx];
        $ref = $array;
    }
}

$foo[1][2][3][3][3] = 'a';
$foo[4][5][6][5][5] = 'b';

$out = array();
transpose($foo, $out);

echo $out[3][3][3][2][1] . ' ' . $out[5][5][6][5][4];

本当にハックで、おそらく最善の解決策ではありませんが、うまくいきます。

基本的に、配列を再帰的にトラバースし、現在のインデックスを配列に蓄積します。
参照された値に達すると、インデックスの「スタック」を取り、それを反転して $out 配列に入れます。($temp 配列の使用を避ける方法はありますか?)

于 2009-04-28T12:17:43.640 に答える
2

連想配列をサポートする転置関数が必要でした:

    $matrix = [
        ['one' => 1, 'two' => 2],
        ['one' => 11, 'two' => 22],
        ['one' => 111, 'two' => 222],
    ];

    $result = \array_transpose($matrix);

    $trans = [
        'one' => [1, 11, 111],
        'two' => [2, 22, 222],
    ];

そして帰り道:

    $matrix = [
        'one' => [1, 11, 111],
        'two' => [2, 22, 222],
    ];

    $result = \array_transpose($matrix);

    $trans = [
        ['one' => 1, 'two' => 2],
        ['one' => 11, 'two' => 22],
        ['one' => 111, 'two' => 222],
    ];

array_unshiftトリックも機能しませんでしたarray_map...

array_map_join_arrayそこで、レコード キーの関連付けを処理する関数をコーディングしました。

/**
 * Similar to array_map() but tries to join values on intern keys.
 * @param callable $callback takes 2 args, the intern key and the list of associated values keyed by array (extern) keys.
 * @param array $arrays the list of arrays to map keyed by extern keys NB like call_user_func_array()
 * @return array
 */
function array_map_join_array(callable $callback, array $arrays)
{
    $keys = [];
    // try to list all intern keys
    array_walk($arrays, function ($array) use (&$keys) {
        $keys = array_merge($keys, array_keys($array));
    });
    $keys = array_unique($keys);
    $res = [];
    // for each intern key
    foreach ($keys as $key) {
        $items = [];
        // walk through each array
        array_walk($arrays, function ($array, $arrKey) use ($key, &$items) {
            if (isset($array[$key])) {
                // stack/transpose existing value for intern key with the array (extern) key
                $items[$arrKey] = $array[$key];
            } else {
                // or stack a null value with the array (extern) key
                $items[$arrKey] = null;
            }
        });
        // call the callback with intern key and all the associated values keyed with array (extern) keys
        $res[$key] = call_user_func($callback, $key, $items);
    }
    return $res;
}

そしてarray_transpose明らかになりました:

function array_transpose(array $matrix)
{
    return \array_map_join_array(function ($key, $items) {
        return $items;
    }, $matrix);
}
于 2017-05-23T13:20:26.257 に答える
1

私は同じ問題に直面しました。これが私が思いついたものです:

function array_transpose(array $arr)
{
    $keys    = array_keys($arr);
    $sum     = array_values(array_map('count', $arr));

    $transposed = array();

    for ($i = 0; $i < max($sum); $i ++)
    {
        $item = array();
        foreach ($keys as $key)
        {
            $item[$key] = array_key_exists($i, $arr[$key]) ? $arr[$key][$i] : NULL;
        }
        $transposed[] = $item;
    }
    return $transposed;
}
于 2016-02-16T16:31:37.907 に答える
1

Two foreach を使用してこれを行うことができます。ある配列と別の配列を移動して新しい配列を作成する次の
ように:

$foo = array(
    'a' => array(
       1 => 'a1',
       2 => 'a2',
       3 => 'a3' 
    ),
    'b' => array(
       1 => 'b1',
       2 => 'b2',
       3 => 'b3' 
    ),
    'c' => array(
       1 => 'c1',
       2 => 'c2',
       3 => 'c3' 
    )
);

$newFoo = [];
foreach($foo as $a => $k){
   foreach($k as $i => $j){
       $newFoo[$i][]= $j;
   }
}

出力を確認する

echo "<pre>";
print_r($newFoo);
echo "</pre>";
于 2020-09-09T06:36:56.333 に答える
1

Codler の答えは、単一行の行列 (例: [[1,2]]) と空の行列 ( []) の場合に失敗します。これらは特殊なケースにする必要があります。

function transpose(array $matrix): array {
    if (!$matrix) return [];
    return array_map(count($matrix) == 1 ? fn ($x) => [$x] : null, ...$matrix);
}

(注: PHP 7.4+ の構文、古いバージョンにも簡単に適応できます)

于 2022-01-21T15:12:46.227 に答える