Ich bin sicher, dass dies eine äußerst offensichtliche Frage ist und dass es eine Funktion gibt, die genau dies tut, aber ich kann sie scheinbar nicht finden. In PHP möchte ich wissen, ob mein Array so effizient wie möglich Duplikate enthält. Ich möchte sie nicht wie bisher entfernen array_unique
, und ich möchte sie nicht besonders ausführen array_unique
und mit dem ursprünglichen Array vergleichen, um festzustellen, ob sie gleich sind, da dies sehr ineffizient erscheint. In Bezug auf die Leistung besteht die "erwartete Bedingung" darin, dass das Array keine Duplikate enthält.
Ich möchte nur in der Lage sein, so etwas zu tun
if (no_dupes($array))
// this deals with arrays without duplicates
else
// this deals with arrays with duplicates
Gibt es eine offensichtliche Funktion, an die ich nicht denke?
Wie erkenne ich doppelte Werte im PHP-Array?
hat den richtigen Titel und ist eine sehr ähnliche Frage. Wenn Sie die Frage jedoch tatsächlich lesen, sucht er nach array_count_values.
quelle
if(count($array) == count(array_unique($array)))
ist das Beste, was Sie bekommen können. Sie müssen das Array auf die eine oder andere Weise durchlaufen, und ich denke, die eingebauten sind dafür optimiert.array_flip
könnte auch in Betracht gezogen werden.Antworten:
Du kannst tun:
function has_dupes($array) { $dupe_array = array(); foreach ($array as $val) { if (++$dupe_array[$val] > 1) { return true; } } return false; }
quelle
return
Zeitpunkt eine O (n) -Funktion ist. Zusätzlich zum Overheadforeach
und Tracking$dupe_array
würde ich gerne ein Benchmarking sehen. Ich würde vermuten, dass für Arrays ohne Duplikate die Verwendung nativer Funktionen schneller ist. Auf jeden Fall besser als O (n ^ 2). Nett.undefined offset
Fehler in PHP. Stattdessen habe ich:foreach ( $a as $v ) { if ( array_key_exists($v,$dupe) { return true; } else { $dupe[$v] = true; }
$dupe_array
mit keinem Wert definiert wurde,$dupe_array[$val]
sollte ein undefinierter Index zurückgegeben werden!Ich weiß, dass du nicht danach bist
array_unique()
. Sie werden jedoch weder einemagischeoffensichtliche Funktion finden, noch wird das Schreiben schneller sein als die Verwendung der nativen Funktionen.Ich schlage vor:
function array_has_dupes($array) { // streamline per @Felix return count($array) !== count(array_unique($array)); }
Passen Sie den zweiten Parameter von
array_unique()
an Ihre Vergleichsanforderungen an.quelle
array_unique
wissen sollten, ob Dupes vorhanden sind, wenn Sie mit dem Ausführen der integrierten Funktionen fertig sind . Alles, was mindestens so viel Arbeitarray_unique
leistet wie mehr als nötig. Obwohl ja, wenn eine solche Funktion nicht existiert, habe ich keine besondere Lust, sie zu schreiben.array_unique
etwas langsam. Wenn Sie wissen, dass das Array nur Ganzzahlen und Zeichenfolgen enthält, können Sie es durch ersetzen,array_flip
um schnellere Ergebnisse zu erzielen.⚡ LEISTUNGSLÖSUNG ⚡
Wenn Sie sich für Leistung und Mikrooptimierungen interessieren, überprüfen Sie diesen Einzeiler:
function no_dupes(array $input_array) { return count($input_array) === count(array_flip($input_array)); }
Beschreibung:
Die Funktion vergleicht die Anzahl der Array-Elemente
$input_array
mit den Elementen von array_flip . Werte werden zu Schlüsseln und raten Sie mal - Schlüssel müssen in assoziativen Arrays eindeutig sein, damit keine eindeutigen Werte verloren gehen und die endgültige Anzahl der Elemente niedriger als das Original ist.Wie gesagt in manuellen Array - Schlüssel kann nur der Typ sein ,
int
oderstring
so ist es das , was Sie in Original - Array Werte haben zu vergleichen, sonst wird PHP beginnen Gießen mit unerwarteten Ergebnissen.Beweis für 10M RECORDS ARRAY
Testfall:
<?php $elements = array_merge(range(1,10000000),[1]); $time = microtime(true); accepted_solution($elements); echo 'Accepted solution: ', (microtime(true) - $time), 's', PHP_EOL; $time = microtime(true); most_voted_solution($elements); echo 'Most voted solution: ', (microtime(true) - $time), 's', PHP_EOL; $time = microtime(true); this_answer_solution($elements); echo 'This answer solution: ', (microtime(true) - $time), 's', PHP_EOL; function accepted_solution($array){ $dupe_array = array(); foreach($array as $val){ // sorry, but I had to add below line to remove millions of notices if(!isset($dupe_array[$val])){$dupe_array[$val]=0;} if(++$dupe_array[$val] > 1){ return true; } } return false; } function most_voted_solution($array) { return count($array) !== count(array_unique($array)); } function this_answer_solution(array $input_array) { return count($input_array) === count(array_flip($input_array)); }
Beachten Sie, dass die akzeptierte Lösung unter bestimmten Umständen schneller sein kann, wenn sich nicht eindeutige Werte am Anfang eines großen Arrays befinden.
quelle
int
oderstring
so sein können. Dies müssen Ihre Werte im Array sein, um sie zu vergleichen.As said in manual array keys can be only type of int or string so this is what you can have in original array values to compare, otherwise PHP will start casting with unexpected results.
.array_flip
die native PHP-Funktion in C geschrieben ist und das Umdrehen ziemlich einfach ist. Nach dem Umdrehen werden nicht eindeutige Werte entfernt, da dies zu einem Array-Schlüsselkonflikt führen kann.$hasDuplicates = count($array) > count(array_unique($array));
Wird sein,
true
wenn Duplikate oderfalse
wenn keine Duplikate.quelle
$duplicate = false; if(count(array) != count(array_unique(array))){ $duplicate = true; }
quelle
Hier ist meine Meinung dazu… Nach einigem Benchmarking fand ich, dass dies die schnellste Methode dafür ist.
function has_duplicates( $array ) { return count( array_keys( array_flip( $array ) ) ) !== count( $array ); }
… Oder je nach Umständen könnte dies geringfügig schneller sein.
function has_duplicates( $array ) { $array = array_count_values( $array ); rsort( $array ); return $array[0] > 1; }
quelle
array_keys()
in Ihrer Antwort brauchen .array_flip()
Verdichtet Ihr Array bereits, wenn die Werte gleich sind. Auch!=
ist ein ausreichender Vergleich, da die Typen von Natur aus gleich sindcount()
(Sie sind derjenige, der Benchmarking erwähnt hat). Daherreturn count(array_flip($arr)) != count($arr);
sollte ausreichend sein.Halte es einfach, dumm! ;)
Einfache ODER-Logik ...
function checkDuplicatesInArray($array){ $duplicates=FALSE; foreach($array as $k=>$i){ if(!isset($value_{$i})){ $value_{$i}=TRUE; } else{ $duplicates|=TRUE; } } return ($duplicates); }
Grüße!
quelle
Zwei Möglichkeiten, es effizient zu machen, die ich mir vorstellen kann:
Einfügen aller Werte in eine Hashtabelle und Überprüfen, ob der Wert, den Sie einfügen, bereits darin enthalten ist (erwartete O (n) Zeit und O (n) Raum)
Sortieren des Arrays und anschließendes Überprüfen, ob benachbarte Zellen je nach Sortieralgorithmus gleich sind (O (nlogn) -Zeit und O (1) - oder O (n) -Raum)
Die Lösung von Stormdrain wäre wahrscheinlich O (n ^ 2), ebenso wie jede Lösung, bei der das Array nach jedem Element durchsucht wird, das nach einem Duplikat sucht
quelle
Finden Sie diese nützliche Lösung
function get_duplicates( $array ) { return array_unique( array_diff_assoc( $array, array_unique( $array ) ) ); }
Nach dieser Zählung Ergebnis, wenn größer als 0 als Duplikate sonst eindeutig.
quelle
Ich benutze dies:
if(count($array)==count(array_count_values($array))){ echo("all values are unique"); }else{ echo("there's dupe values"); }
Ich weiß nicht, ob es das schnellste ist, aber es funktioniert bisher ziemlich gut
quelle
function hasDuplicate($array){ $d = array(); foreach($array as $elements) { if(!isset($d[$elements])){ $d[$elements] = 1; }else{ return true; } } return false; }
quelle
Wie Sie ausdrücklich sagten, dass Sie nicht verwenden wollten,
array_unique
werde ich die anderen Antworten ignorieren, obwohl sie wahrscheinlich besser sind.Warum verwenden Sie nicht array_count_values () und prüfen dann, ob das resultierende Array einen Wert größer als 1 hat?
quelle
PHP hat eine Funktion zum Zählen der Vorkommen im Array http://www.php.net/manual/en/function.array-count-values.php
quelle
Sie können es auch so machen: Dies gibt true zurück, wenn unique else false zurückgibt.
$nofollow = (count($modelIdArr) !== count(array_unique($modelIdArr))) ? true : false;
quelle
Die einfache Lösung aber ganz schneller.
$elements = array_merge(range(1,10000000),[1]); function unique_val_inArray($arr) { $count = count($arr); foreach ($arr as $i_1 => $value) { for($i_2 = $i_1 + 1; $i_2 < $count; $i_2++) { if($arr[$i_2] === $arr[$i_1]){ return false; } } } return true; } $time = microtime(true); unique_val_inArray($elements); echo 'This solution: ', (microtime(true) - $time), 's', PHP_EOL;
Geschwindigkeit - [0,71]!
quelle