Ich benötige ein PHP-Objekt ähnlich wie HashMap in Java, aber ich habe es nicht gefunden, als ich gegoogelt habe. Wenn also jemand weiß, wie ich HashMaps in PHP nachahmen kann, wäre Hilfe willkommen.
Ich benötige Schlüssel / Wert-Paare und ich muss Schlüssel als Array aus der Karte erhalten.
Neuling
1
$keys = array_keys($array);(und siehe auch Sushils Antwort unten)
KingCrunch
Arrays sind tatsächlich die einzige Datenstruktur in PHP (wenn Sie Klassen / Objekte nicht als Datenstruktur betrachten). Es bietet eine Schlüssel- / Wertestruktur und Sie können die Schlüssel leicht mit erhalten array_keys. Sie können eine Wrapper-Klasse schreiben, wenn Sie möchten.
Felix Kling
Antworten:
93
Arrays in PHP können eine Schlüsselwertstruktur haben.
@Gabi: Wenn es wie eine Ente läuft, wie eine Ente schwimmt und wie eine Ente quakt ... PHP-Handbuch sagt: Ein Array in PHP ist eigentlich eine geordnete Karte.
Felix Kling
115
@ Felix Kling AFAIK PHP-Arrays haben keine O (1) Suche / Einfügung / Löschung, so dass sie nicht wie Hashmaps quaken
SplObjectStorage hat einige Nachteile: Wenn Sie foreach verwenden, sind die Schlüssel Ganzzahlen. Und Sie können keine Liste von Schlüsseln und Werten daraus abrufen. In meinem Fall habe ich mich für eine benutzerdefinierte Klasse entschieden, die ArrayAccess, Iterator und Countable implementiert.
Die Komplexität von $myhashmap['mykey2']in diesem Fall scheint die konstante Zeit O (1) zu sein, was bedeutet, dass die Zeit, die zum Abrufen eines Werts bei einem Schlüssel benötigt wird, gleich bleibt, wenn sich die Größe von $ myhasmap der Unendlichkeit nähert.
Der Nachweis, dass das gelesene PHP-Array eine konstante Zeit ist:
Die Schleife fügt 1 Milliarde Schlüssel / Werte hinzu. Es dauert ungefähr 2 Minuten, um alle zur Hashmap hinzuzufügen, was Ihren Speicher erschöpfen kann.
Dann sehen Sie, wie lange es dauert, eine Suche durchzuführen:
Das 10333ist der Schlüssel, den wir nachgeschlagen haben. 1 Million Nanosekunden == 1 Millisekunde. Die Zeit, die benötigt wird, um einen Wert von einem Schlüssel zu erhalten, beträgt 2,06 Millionen Nanosekunden oder etwa 2 Millisekunden. Ungefähr die gleiche Zeit, wenn das Array leer war. Das sieht für mich nach ständiger Zeit aus.
Keine konstante Zeit ... Angenommen, die zugrunde liegende Implementierung ist eine Array-basierte Hashmap. Aufgrund der Notwendigkeit, Kollisionen zu behandeln, ist das Beste, was Sie tun können, O (log n), wenn Kollisionen als selbstausgeglichen gespeichert werden. Bäume (wie die Java-Implementierung von Hashmap), können aber sogar in einer verknüpften Liste (Verkettung) gespeichert werden, was einen Worst-Case von O (n) ergibt. Dies gilt sowohl für das Einfügen als auch für das Nachschlagen, aber der durchschnittliche Fall liegt nahe bei O (1) ...
Daniel Valland
1
Bei einer Datensatzgröße, die den gesamten Speicher eines Computers belegt (z. B. 8 GB), beträgt die Suchzeit einige Millisekunden. Es ist also "so nahe an der konstanten Zeit, es ist im Grunde eine konstante Zeit", aber wenn Sie mathematisch korrekt sein wollen, um Dinge mit 10 Milliarden Kisten bis ins Unendliche auszuführen, ist es O (n log n). Ich kann auch nicht picken. :) Ich benutze konstante Zeit hier bedeutet "Dies wird nicht dein Engpass sein, Bruder, nicht einmal Stolperhund".
Eric Leschinski
Ich stimme zu, es wird wahrscheinlich kein Engpass sein, da O (log n) für alle Operationen immer noch sehr schnell ist. Der Punkt ist nur, dass der einzige Weg, um konstantes Zeit-Hashing zu erhalten, darin besteht, dass die Hash-Funktion perfekt ist und keine Colission existieren kann. Wenn nicht perfekt, ist das Beste, was Sie bekommen, O (log n). Laut: phpinternalsbook.com/hashtables/basic_structure.html verwendet php jedoch eine Verkettung, die den schlimmsten Fall von O (N) aufweist. Ich weiß nicht, ob dies der Fall ist, da ich erwarten würde, dass eine Lösung verwendet wird, die log n erreicht, wie z. B. ein selbstausgeglichener Baum, aber wenn dies der Fall ist, die Unterscheidung zwischen O (N) und O (1) ) ist nicht trivial.
Was ist, wenn ich ein leeres Array deklarieren und die Zuweisungen wie folgt ausführen möchte: "fruits" => array("a" => "Orange", "b" => "Banana", "c" => "Apple")after?
Diegoaguilar
2
@Diego $fruits = array(); $fruits['fruits'] = array('a' => 'Orange',...);... eigentlich können Sie dies sogar gleich von Anfang an tun: $fruits['fruits']['a'] = 'Orange'; $fruits['holes']['first'] = 5; $fruits['numbers'][] = 1;Sie müssen nicht einmal unbedingt eines der Arrays mit erstellen array().
Zamnuts
10
HashMap, das auch mit anderen Schlüsseln als Zeichenfolgen und Ganzzahlen mit O (1) -Lesekomplexität funktioniert (abhängig von der Qualität Ihrer eigenen Hash-Funktion).
Sie können selbst eine einfache HashMap erstellen. Eine HashMap speichert Elemente in einem Array unter Verwendung des Hash als Index / Schlüssel. Hash-Funktionen führen gelegentlich zu Kollisionen (nicht oft, aber möglicherweise), sodass Sie mehrere Elemente für einen Eintrag in der HashMap speichern müssen. So einfach ist eine HashMap:
Damit es funktioniert, benötigen Sie auch eine Hash-Funktion für Ihren Schlüssel und einen Vergleicher für Gleichheit (wenn Sie nur wenige Elemente haben oder aus einem anderen Grund keine Geschwindigkeit benötigen, können Sie die Hash-Funktion 0 zurückgeben lassen; alle Elemente sind in den gleichen Eimer geben und Sie erhalten O (N) Komplexität)
$keys = array_keys($array);
(und siehe auch Sushils Antwort unten)array_keys
. Sie können eine Wrapper-Klasse schreiben, wenn Sie möchten.Antworten:
Arrays in PHP können eine Schlüsselwertstruktur haben.
quelle
Je nachdem, was Sie möchten, könnte Sie die SPL Object Storage-Klasse interessieren.
http://php.net/manual/en/class.splobjectstorage.php
Sie können Objekte als Schlüssel verwenden, haben eine Schnittstelle zum Zählen, Abrufen des Hash und anderer Extras.
$s = new SplObjectStorage; $o1 = new stdClass; $o2 = new stdClass; $o2->foo = 'bar'; $s[$o1] = 'baz'; $s[$o2] = 'bingo'; echo $s[$o1]; // 'baz' echo $s[$o2]; // 'bingo'
quelle
Erstellen Sie eine Java wie HashMap in PHP mit O (1) Lesekomplexität.
Öffnen Sie ein PHPsh-Terminal:
php> $myhashmap = array(); php> $myhashmap['mykey1'] = 'myvalue1'; php> $myhashmap['mykey2'] = 'myvalue2'; php> echo $myhashmap['mykey2']; myvalue2
Die Komplexität von
$myhashmap['mykey2']
in diesem Fall scheint die konstante Zeit O (1) zu sein, was bedeutet, dass die Zeit, die zum Abrufen eines Werts bei einem Schlüssel benötigt wird, gleich bleibt, wenn sich die Größe von $ myhasmap der Unendlichkeit nähert.Der Nachweis, dass das gelesene PHP-Array eine konstante Zeit ist:
Führen Sie dies durch den PHP-Interpreter:
php> for($x = 0; $x < 1000000000; $x++){ ... $myhashmap[$x] = $x . " derp"; ... }
Die Schleife fügt 1 Milliarde Schlüssel / Werte hinzu. Es dauert ungefähr 2 Minuten, um alle zur Hashmap hinzuzufügen, was Ihren Speicher erschöpfen kann.
Dann sehen Sie, wie lange es dauert, eine Suche durchzuführen:
php> system('date +%N');echo " " . $myhashmap[10333] . " ";system('date +%N'); 786946389 10333 derp 789008364
Wie schnell sucht die PHP-Array-Karte?
Das
10333
ist der Schlüssel, den wir nachgeschlagen haben. 1 Million Nanosekunden == 1 Millisekunde. Die Zeit, die benötigt wird, um einen Wert von einem Schlüssel zu erhalten, beträgt 2,06 Millionen Nanosekunden oder etwa 2 Millisekunden. Ungefähr die gleiche Zeit, wenn das Array leer war. Das sieht für mich nach ständiger Zeit aus.quelle
$fruits = array ( "fruits" => array("a" => "Orange", "b" => "Banana", "c" => "Apple"), "numbers" => array(1, 2, 3, 4, 5, 6), "holes" => array("first", 5 => "second", "third") ); echo $fruits["fruits"]["b"]
gibt 'Banane' aus
entnommen aus http://in2.php.net/manual/en/function.array.php
quelle
"fruits" => array("a" => "Orange", "b" => "Banana", "c" => "Apple")
after?$fruits = array(); $fruits['fruits'] = array('a' => 'Orange',...);
... eigentlich können Sie dies sogar gleich von Anfang an tun:$fruits['fruits']['a'] = 'Orange'; $fruits['holes']['first'] = 5; $fruits['numbers'][] = 1;
Sie müssen nicht einmal unbedingt eines der Arrays mit erstellenarray()
.HashMap, das auch mit anderen Schlüsseln als Zeichenfolgen und Ganzzahlen mit O (1) -Lesekomplexität funktioniert (abhängig von der Qualität Ihrer eigenen Hash-Funktion).
Sie können selbst eine einfache HashMap erstellen. Eine HashMap speichert Elemente in einem Array unter Verwendung des Hash als Index / Schlüssel. Hash-Funktionen führen gelegentlich zu Kollisionen (nicht oft, aber möglicherweise), sodass Sie mehrere Elemente für einen Eintrag in der HashMap speichern müssen. So einfach ist eine HashMap:
class IEqualityComparer { public function equals($x, $y) { throw new Exception("Not implemented!"); } public function getHashCode($obj) { throw new Exception("Not implemented!"); } } class HashMap { private $map = array(); private $comparer; public function __construct(IEqualityComparer $keyComparer) { $this->comparer = $keyComparer; } public function has($key) { $hash = $this->comparer->getHashCode($key); if (!isset($this->map[$hash])) { return false; } foreach ($this->map[$hash] as $item) { if ($this->comparer->equals($item['key'], $key)) { return true; } } return false; } public function get($key) { $hash = $this->comparer->getHashCode($key); if (!isset($this->map[$hash])) { return false; } foreach ($this->map[$hash] as $item) { if ($this->comparer->equals($item['key'], $key)) { return $item['value']; } } return false; } public function del($key) { $hash = $this->comparer->getHashCode($key); if (!isset($this->map[$hash])) { return false; } foreach ($this->map[$hash] as $index => $item) { if ($this->comparer->equals($item['key'], $key)) { unset($this->map[$hash][$index]); if (count($this->map[$hash]) == 0) unset($this->map[$hash]); return true; } } return false; } public function put($key, $value) { $hash = $this->comparer->getHashCode($key); if (!isset($this->map[$hash])) { $this->map[$hash] = array(); } $newItem = array('key' => $key, 'value' => $value); foreach ($this->map[$hash] as $index => $item) { if ($this->comparer->equals($item['key'], $key)) { $this->map[$hash][$index] = $newItem; return; } } $this->map[$hash][] = $newItem; } }
Damit es funktioniert, benötigen Sie auch eine Hash-Funktion für Ihren Schlüssel und einen Vergleicher für Gleichheit (wenn Sie nur wenige Elemente haben oder aus einem anderen Grund keine Geschwindigkeit benötigen, können Sie die Hash-Funktion 0 zurückgeben lassen; alle Elemente sind in den gleichen Eimer geben und Sie erhalten O (N) Komplexität)
Hier ist ein Beispiel:
class IntArrayComparer extends IEqualityComparer { public function equals($x, $y) { if (count($x) !== count($y)) return false; foreach ($x as $key => $value) { if (!isset($y[$key]) || $y[$key] !== $value) return false; } return true; } public function getHashCode($obj) { $hash = 0; foreach ($obj as $key => $value) $hash ^= $key ^ $value; return $hash; } } $hashmap = new HashMap(new IntArrayComparer()); for ($i = 0; $i < 10; $i++) { for ($j = 0; $j < 10; $j++) { $hashmap->put(array($i, $j), $i * 10 + $j); } } echo $hashmap->get(array(3, 7)) . "<br/>"; echo $hashmap->get(array(5, 1)) . "<br/>"; echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>"; echo ($hashmap->has(array(-1, 9))? 'true': 'false') . "<br/>"; echo ($hashmap->has(array(6))? 'true': 'false') . "<br/>"; echo ($hashmap->has(array(1, 2, 3))? 'true': 'false') . "<br/>"; $hashmap->del(array(8, 4)); echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";
Welches gibt als Ausgabe:
37 51 true false false false false
quelle
IEqualityComparer
sollte eininterface
hier sein