Gibt es eine Möglichkeit, so etwas zu tun:
$test_array = array(
"first_key" => "first_value",
"second_key" => "second_value"
);
var_dump(
array_map(
function($a, $b) {
return "$a loves $b";
},
array_keys($test_array),
array_values($test_array)
)
);
Aber anstatt anzurufen array_keys
und array_values
direkt vorbei an der $test_array
Variable?
Die gewünschte Ausgabe ist:
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
Nicht mit array_map, da es keine Schlüssel verarbeitet.
array_walk tut:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
array_walk($test_array, function(&$a, $b) { $a = "$b loves $a"; });
var_dump($test_array);
// array(2) {
// ["first_key"]=>
// string(27) "first_key loves first_value"
// ["second_key"]=>
// string(29) "second_key loves second_value"
// }
Es ändert jedoch das als Parameter angegebene Array, es handelt sich also nicht genau um eine funktionale Programmierung (da Sie die Frage so gekennzeichnet haben). Wie im Kommentar erwähnt, werden dadurch nur die Werte des Arrays geändert, sodass die Schlüssel nicht die sind, die Sie in der Frage angegeben haben.
Sie könnten eine Funktion schreiben, die die oben genannten Punkte selbst behebt, wenn Sie möchten, wie folgt:
function mymapper($arrayparam, $valuecallback) {
$resultarr = array();
foreach ($arrayparam as $key => $value) {
$resultarr[] = $valuecallback($key, $value);
}
return $resultarr;
}
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
$new_array = mymapper($test_array, function($a, $b) { return "$a loves $b"; });
var_dump($new_array);
// array(2) {
// [0]=>
// string(27) "first_key loves first_value"
// [1]=>
// string(29) "second_key loves second_value"
// }
Dies ist wahrscheinlich die kürzeste und einfachste Begründung:
$states = array('az' => 'Arizona', 'al' => 'Alabama');
array_map(function ($short, $long) {
return array(
'short' => $short,
'long' => $long
);
}, array_keys($states), $states);
// produces:
array(
array('short' => 'az', 'long' => 'Arizona'),
array('short' => 'al', 'long' => 'Alabama')
)
Hier ist meine sehr einfache, PHP 5.5-kompatible Lösung:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
Der von Ihnen bereitgestellte Aufruf sollte selbst ein Array mit zwei Werten zurückgeben, dh return [key, value]
. Der innere Ruf nach array_map
erzeugt daher ein Array von Arrays. Dieses wird dann von wieder in ein eindimensionales Array konvertiert array_column
.
Verwendungszweck
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Ausgabe
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
Teilanwendung
Falls Sie die Funktion viele Male mit verschiedenen Arrays, aber derselben Zuordnungsfunktion verwenden müssen, können Sie eine sogenannte partielle Funktionsanwendung (bezogen auf ‘Curry‘), wodurch Sie das Datenarray nur beim Aufruf übergeben können:
function array_map_assoc_partial(callable $f) {
return function (array $a) use ($f) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
};
}
...
$my_mapping = array_map_assoc_partial($func);
var_dump($my_mapping($ordinals));
Was die gleiche Ausgabe erzeugt, gegeben $func
und $ordinals
sind wie früher.
HINWEIS: Wenn Ihre zugeordnete Funktion die zurückgibt gleichen Schlüssel bei zwei unterschiedlichen Eingängen der zugeordnete Wert der spätere Schlüssel gewinnt. Kehren Sie das Eingabearray um und geben Sie das Ergebnis von aus array_map_assoc
um früheren Schlüsseln zu erlauben, zu gewinnen. (Die zurückgegebenen Schlüssel in meinem Beispiel können nicht kollidieren, da sie den Schlüssel des Quellarrays enthalten, der wiederum eindeutig sein muss.)
Alternative
Das Folgende ist eine Variante des Obigen, die sich für manche als logischer erweisen könnte, aber PHP 5.6 erfordert:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
In dieser Variante sollte Ihre bereitgestellte Funktion (über die das Datenarray abgebildet wird) stattdessen ein assoziatives Array mit einer Zeile zurückgeben, dh return [key => value]
. Das Ergebnis des Mappings des Callable wird dann einfach entpackt und übergeben array_merge
. Wie zuvor führt die Rückgabe eines doppelten Schlüssels dazu, dass spätere Werte gewinnen.
nb Alex83690 hat in einem Kommentar darauf hingewiesen, dass using array_replace
hier statt array_merge
würde ganzzahlige Schlüssel beibehalten. array_replace
ändert das Eingabearray nicht und ist daher sicher für Funktionscode.
Wenn Sie PHP 5.3 bis 5.5 verwenden, ist Folgendes äquivalent. Es verwendet array_reduce
und die binäre +
Array-Operator zum Konvertieren des resultierenden zweidimensionalen Arrays in ein eindimensionales Array unter Beibehaltung der Schlüssel:
function array_map_assoc(callable $f, array $a) {
return array_reduce(array_map($f, array_keys($a), $a), function (array $acc, array $a) {
return $acc + $a;
}, []);
}
Verwendungszweck
Beide dieser Varianten würden also verwendet werden:
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Beachten Sie das =>
Anstatt von ,
in $func
.
Die Ausgabe ist die gleiche wie zuvor, und jede kann teilweise auf die gleiche Weise wie zuvor angewendet werden.
Zusammenfassung
Das Ziel der ursprünglichen Frage besteht darin, den Aufruf des Aufrufs so einfach wie möglich zu gestalten, auf Kosten einer komplizierteren Funktion, die aufgerufen wird. insbesondere um die Möglichkeit zu haben, das Datenarray als einzelnes Argument zu übergeben, ohne die Schlüssel und Werte aufzuteilen. Verwenden Sie die am Anfang dieser Antwort angegebene Funktion:
$test_array = ["first_key" => "first_value",
"second_key" => "second_value"];
$array_map_assoc = function (callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
};
$f = function ($key, $value) {
return [$key, $key . ' loves ' . $value];
};
var_dump(array_values($array_map_assoc($f, $test_array)));
Oder wir können nur für diese Frage eine Vereinfachung zu machen array_map_assoc()
Funktion, die Ausgabeschlüssel löscht, da die Frage nicht danach fragt:
$test_array = ["first_key" => "first_value",
"second_key" => "second_value"];
$array_map_assoc = function (callable $f, array $a) {
return array_map($f, array_keys($a), $a);
};
$f = function ($key, $value) {
return $key . ' loves ' . $value;
};
var_dump($array_map_assoc($f, $test_array));
Die Antwort lautet also NEINSie können es nicht vermeiden anzurufen array_keys
aber Sie können die Stelle wo abstrahieren array_keys
wird in eine Funktion höherer Ordnung aufgerufen, was gut genug sein könnte.
$array = [
'category1' => 'first category',
'category2' => 'second category',
];
$new = array_map(function($key, $value) {
return "{$key} => {$value}";
}, array_keys($array), $array);
Ich werde noch eine weitere Lösung für das Problem mit Version 5.6 oder höher hinzufügen. Ich weiß nicht, ob es effizienter ist als die bereits großartigen Lösungen (wahrscheinlich nicht), aber für mich ist es einfach einfacher zu lesen:
$myArray = [
"key0" => 0,
"key1" => 1,
"key2" => 2
];
array_combine(
array_keys($myArray),
array_map(
function ($intVal) {
return strval($intVal);
},
$myArray
)
);
Verwenden strval()
als Beispielfunktion in der array_map
dies erzeugt:
array(3) {
["key0"]=>
string(1) "0"
["key1"]=>
string(1) "1"
["key2"]=>
string(1) "2"
}
Hoffentlich bin ich nicht der Einzige, der das ziemlich einfach zu verstehen findet.
array_combine
schafft ein key => value
Array aus einem Array von Schlüsseln und einem Array von Werten, der Rest ist ziemlich selbsterklärend.
Schau hier! Es gibt eine triviale Lösung!
function array_map2(callable $f, array $a)
{
return array_map($f, array_keys($a), $a);
}
Wie in der Frage gesagt, array_map
hat bereits genau die benötigte Funktionalität. Die anderen Antworten hier verkomplizieren die Dinge ernsthaft: array_walk
ist nicht funktionsfähig.
Verwendungszweck
Genau so, wie Sie es von Ihrem Beispiel erwarten würden:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));