
Calvin
Wie würden Sie ein mehrdimensionales Array in PHP um 90 Grad drehen (transponieren)? Zum Beispiel:
// 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"
}
Wie würden Sie umsetzen flipDiagonally()
?
Edit: Das ist keine Hausaufgabe. Ich möchte nur sehen, ob irgendwelche SOers eine kreativere Lösung als die offensichtlichste Route haben. Aber da sich einige Leute darüber beschwert haben, dass dieses Problem zu einfach ist, wie wäre es mit einer allgemeineren Lösung, die mit einem n funktioniertth Dimensions-Array?
dh Wie würden Sie eine Funktion schreiben, damit:
$foo[j][k][...][x][y][z] = $bar[z][k][...][x][y][j]
?(ps. Ich glaube nicht, dass 12 verschachtelt sind for loops
ist in diesem Fall die beste Lösung.)

Kodler
function transpose($array) {
array_unshift($array, null);
return call_user_func_array('array_map', $array);
}
Oder wenn Sie PHP 5.6 oder höher verwenden:
function transpose($array) {
return array_map(null, ...$array);
}
Mit 2 Schlaufen.
function flipDiagonally($arr) {
$out = array();
foreach ($arr as $key => $subarr) {
foreach ($subarr as $subkey => $subvalue) {
$out[$subkey][$key] = $subvalue;
}
}
return $out;
}
Ich denke du meinst das Array transponieren (Spalten werden zu Zeilen, Zeilen werden zu Spalten).
Hier ist eine Funktion, die das für Sie erledigt (Quelle):
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;
}
Transponieren eines N-dimensionalen Arrays:
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];
Wirklich hackish und wahrscheinlich nicht die beste Lösung, aber hey, es funktioniert.
Grundsätzlich durchläuft es das Array rekursiv und sammelt die aktuellen Indizes in einem Array.
Sobald es den referenzierten Wert erreicht hat, nimmt es den “Stapel” von Indizes und kehrt ihn um, indem es ihn in das $out-Array einfügt. (Gibt es eine Möglichkeit, die Verwendung des $temp-Arrays zu vermeiden?)

seltsam
Ich brauchte eine Transponierungsfunktion mit Unterstützung für assoziatives Array:
$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],
];
Und der Rückweg:
$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],
];
Die array_unshift
Trick funktionierte NOCH nicht array_map
…
Also habe ich a codiert array_map_join_array
Funktion zum Umgang mit der Zuordnung von Datensatzschlüsseln:
/**
* 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;
}
und array_transpose
wurde offensichtlich:
function array_transpose(array $matrix)
{
return \array_map_join_array(function ($key, $items) {
return $items;
}, $matrix);
}

mickmackusa
Wenn Sie versuchen, die Beispieldaten des OP mit dem Splat-Operator (...
), erzeugen Sie:
Schwerwiegender Fehler: Nicht erfasster Fehler: Array mit Zeichenfolgenschlüsseln kann nicht entpackt werden
Nachweisen
Rufen Sie an, um diesen Fehler zu beheben array_values()
um die Schlüssel der ersten Ebene vor dem Auspacken zu indizieren.
var_export(array_map(null, ...array_values($foo)));
Ausgabe:
array (
0 =>
array (
0 => 'a1',
1 => 'b1',
2 => 'c1',
),
1 =>
array (
0 => 'a2',
1 => 'b2',
2 => 'c2',
),
2 =>
array (
0 => 'a3',
1 => 'b3',
2 => 'c3',
),
)
Eine zusätzliche Besonderheit/Überraschung bezüglich der Transponierung mit dieser Technik ist die null
Elemente werden generiert, wenn die Subarrays unterschiedliche Größen haben … aber vielleicht nicht dort, wo Sie es erwarten würden.
Aus Beispieldaten wie diesen:
$foo = array(
'a' => array(
1 => 'a1',
2 => 'a2'
),
'b' => array(
1 => 'b1',
3 => 'b3'
),
'c' => array(
1 => 'c1',
2 => 'c2',
3 => 'c3'
)
);
Die Ausgabe ist:
array (
0 =>
array (
0 => 'a1',
1 => 'b1',
2 => 'c1',
),
1 =>
array (
0 => 'a2',
1 => 'b3',
2 => 'c2',
),
2 =>
array (
0 => NULL,
1 => NULL,
2 => 'c3',
),
)
Beachten Sie die Sorgfalt, die diese Funktion an den Tag legt (vergleichbar mit der Gepäckabfertigung, die Ihr Gepäck aus dem Bauch des Flugzeugs holt). Die IDs der ursprünglichen Subarray-Werte werden nicht beachtet (und es wäre egal, ob 1
, 2
& 3
wurden x
, y
& z
); Was auch immer vom Förderband kommt, wird in den niedrigsten verfügbaren Schlitz geworfen.
Dieses Verhalten ist konsistent und zuverlässig beim Liefern einer vollständigen Matrix. EIN foreach()
Schleifenalternative liefert nicht nativ null
Element aus Subarrays unterschiedlicher Größe, und in den meisten Implementierungen hängt seine Fähigkeit, auf alle Subarray-Werte zuzugreifen, von der Länge des ersten Subarrays ab.
$foo = array(
'a' => array(
1 => 'a1',
2 => 'a2'
),
'b' => array(
1 => 'b1',
),
'c' => array(
1 => 'c1',
2 => 'c2',
3 => 'c3'
)
);
foreach (current($foo) as $column => $not_used) {
$result[] = array_column($foo, $column);
}
var_export($result);
Ausgabe:
array (
0 =>
array (
0 => 'a1',
1 => 'b1',
2 => 'c1',
),
1 =>
array (
0 => 'a2',
1 => 'c2',
),
)
Wie oben gezeigt, müssten Sie, wenn Sie sicher sein möchten, dass Sie ALLE Daten aus dem Eingabearray extrahiert haben, eine Additionslogik schreiben, um alle eindeutigen Spalten-IDs an die foreach-Schleife zu liefern.
ps Bevor ich von dieser verkürzten transponierenden Syntax erfuhr, schrieb ich einen hässlicheren, ausführlicheren funktionalen Transposer, der einige Kritik einstecken musste.

José Trindade
Ich wurde mit dem gleichen Problem konfrontiert. Hier ist, was ich herausgefunden habe:
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;
}
9901600cookie-checkTransponieren mehrdimensionaler Arrays in PHPyes
@Calvin Ich weiß, es ist viele Jahre her (11!), Aber … hast du eine Antwort akzeptiert oder nicht? Ist Ihnen aufgefallen, dass die beliebteste Antwort im Grunde falsch ist, weil einzelne Zeilen nicht unterstützt werden [[1,2,…N]]? Schauen Sie sich die Sandbox für die Illustration an: sandbox.onlinephpfunctions.com/code/…
– Onkeltem
3. Februar 2020 um 1:22 Uhr
Außerdem kann der Splat-Operator keine Zeichenfolgenschlüssel entpacken. Beweis des Fehlers: 3v4l.org/1WSQH …hoppla, mir ist gerade aufgefallen, dass ich das vor über einem Jahr als Antwort auf dieser Seite gesagt habe!
– mickmackusa
23. Juni 2020 um 13:20 Uhr