web-dev-qa-db-ja.com

php:配列に重複があるかどうかを確認します

これは非常に明白な質問であり、まさにこれを行う関数があると確信していますが、見つけることができないようです。 PHPでは、可能な限り効率的に配列に重複があるかどうかを知りたいです。 array_uniqueのようにそれらを削除したくはありません。また、array_uniqueを実行して元の配列と比較し、それらが同じかどうかを確認したくはありません。非効率的な。パフォーマンスに関する限り、「予想される条件」は、配列に重複がないことです。

次のようなことができるようになりたい

if (no_dupes($array))
    // this deals with arrays without duplicates
else
    // this deals with arrays with duplicates

私が考えていない明らかな機能はありますか?
PHP配列?
は正しいタイトルで、非常によく似た質問ですが、実際に質問を読んだ場合、彼はarray_count_valuesを探しています。

55
Mala

できるよ:

function has_dupes($array) {
    $dupe_array = array();
    foreach ($array as $val) {
        if (++$dupe_array[$val] > 1) {
            return true;
        }
    }
    return false;
}
37
Mike Sherov

array_unique()の後ではないことを知っています。しかし、あなたは見つけることができません 魔法の obvious関数も、ネイティブ関数を使用するよりも高速な記述もできません。

私が提案する:

_function array_has_dupes($array) {
   // streamline per @Felix
   return count($array) !== count(array_unique($array));
}
_

array_unique() の2番目のパラメーターを調整して、比較のニーズに合わせます。

185
Jason McCreary

⚡パフォーマンスソリューション⚡

パフォーマンスとマイクロ最適化に関心がある場合は、このワンライナーを確認してください。

function no_dupes(array $input_array) {
    return count($input_array) === count(array_flip($input_array));
}

説明:

関数は、$input_arrayの配列要素の数を array_flip 'ed要素と比較します。値はキーになり、推測します。キーは連想配列内で一意でなければならないため、一意の値が失われたり、要素の最終数が元の値よりも少なくなったりしません。

手動 で述べたように、配列キーはintまたはstringのタイプのみであるため、これは比較する元の配列値に含めることができます。それ以外の場合はPHPは、予期しない結果で casting を開始します。

10Mレコードアレイの証明

  • 最も投票された解決策:14.187316179276s ?????????????????????????????????????????????????? ????????????
  • 承認済みのソリューション:2.0736091136932s ????????
  • この回答ソリューション:0.14155888557434s ????/10

テストケース:

<?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));
}

特定の条件では、一意の値が巨大な配列の先頭近くにない場合、受け入れられたソリューションがより高速になる可能性があることに注意してください。

51
s3m3n
$duplicate = false;

 if(count(array) != count(array_unique(array))){
   $duplicate = true;
}
5
SpreadYourWings

これについての私の見解は…ベンチマークを行った結果、これがこのための最速の方法であることがわかりました。

function has_duplicates( $array ) {
    return count( array_keys( array_flip( $array ) ) ) !== count( $array );
}

…または状況によっては、これはわずかに高速になる可能性があります。

function has_duplicates( $array ) {
    $array = array_count_values( $array );
    rsort( $array );
    return $array[0] > 1;
}
4
micadelli
count($array) > count(array_unique($array)); 

重複する場合はfalse、重複しない場合はtrueになります。

4
Andrew

シンプルで愚かなことをしてください! ;)

シンプルOR logic ...

function checkDuplicatesInArray($array){
    $duplicates=FALSE;
    foreach($array as $k=>$i){
        if(!isset($value_{$i})){
            $value_{$i}=TRUE;
        }
        else{
            $duplicates|=TRUE;          
        }
    }
    return ($duplicates);
}

よろしく!

2
Miles Bennet

この便利なソリューションを見つける

function get_duplicates( $array ) {
    return array_unique( array_diff_assoc( $array, array_unique( $array ) ) );
}

カウントが0より大きい場合は、他の一意の重複よりも多くなります。

1
Muhammad Raheel

私はこれを使用しています:

if(count($array)==count(array_count_values($array))){
    echo("all values are unique");
}else{
    echo("there's dupe values");
}

最速かどうかはわかりませんが、これまでのところうまくいきます

0
Abraham Romero

PHPには、配列内の出現回数をカウントする機能があります http://www.php.net/manual/en/function.array-count-values.php

0
mazgalici

そのようにすることもできます:一意のelseがfalseを返す場合、これはtrueを返します。

$nofollow = (count($modelIdArr) !== count(array_unique($modelIdArr))) ? true : false;
0
Lakhan

私が考えることができる2つの効率的な方法:

  1. すべての値をある種のハッシュテーブルに挿入し、挿入する値が既にその中にあるかどうかを確認します(O(n)時間とO(n)スペースが予想されます)

  2. 配列を並べ替え、隣接セルが等しいかどうかを確認します(O(nlogn) timeおよびO(1)またはO(n)スペースは並べ替えに応じてアルゴリズム)

stormdrainの解決策はおそらくO(n ^ 2)であり、各要素の配列をスキャンして重複を検索することを伴う解決策と同様です。

0
Bwmat

あなたが具体的に言ったように、あなたはarray_unique他の回答はおそらくより良いという事実にもかかわらず無視します。

array_count_values() を使用して、結果の配列に1より大きい値があるかどうかを確認してみませんか?

0
delete me