PHP多次元配列検索(特定の値でキーを検索)

私はこの多次元配列を持っています。私はそれを検索し、 "スラッグ"の値に一致するキーだけを返す必要があります。私は、多次元配列の検索に関する他のスレッドがあることを知っていますが、私は自分の状況に適用するのに十分理解していません。助けてくれてありがとう!

だから私は次のような機能が必要です:

myfunction($products,'breville-one-touch-tea-maker-BTM800XL');
// returns 1

ここに配列があります:

$products = array (
1  => array(
        'name'          => 'The Breville One-Touch Tea Maker',
        'slug'          => 'breville-one-touch-tea-maker-BTM800XL',
        'shortname'     => 'The One-Touch Tea Maker',
        'listprice'     => '299.99',
        'price'         => '249.99',
        'rating'        => '9.5',
        'reviews'       => '81',
        'buyurl'        => 'http://www.amazon.com/The-Breville-One-Touch-Tea-Maker/dp/B003LNOPSG',
        'videoref1'     => 'xNb-FOTJY1c',
        'videoref2'     => 'WAyk-O2B6F8',
        'image'         => '812BpgHhjBML.jpg',
        'related1'      => '2',
        'related2'      => '3',
        'related3'      => '4',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => 'K. Martino',
        ),

2  => array(
        'name'          => 'Breville Variable-Temperature Kettle BKE820XL',
        'slug'          => 'breville-variable-temperature-kettle-BKE820XL',
        'shortname'     => 'Variable Temperature Kettle',
        'listprice'     => '199.99',
        'price'         => '129.99',
        'rating'        => '9',
        'reviews'       => '78',
        'buyurl'        => 'http://www.amazon.com/Breville-BKE820XL-Variable-Temperature-1-8-Liter-Kettle/dp/B001DYERBK',
        'videoref1'     => 'oyZWBD83xeE',
        'image'         => '41y2B8jSKmwL.jpg',
        'related1'      => '3',
        'related2'      => '4',
        'related3'      => '5',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => '',
        ),
);
73
追加された
ビュー: 1

8 答え

非常に単純です:

function myfunction($products, $field, $value)
{
   foreach($products as $key => $product)
   {
      if ( $product[$field] === $value )
         return $key;
   }
   return false;
}
117
追加された
条件付きステートメントでこの関数を使用している場合、戻り値のキーにインデックスが[0]あることがあるため、型に対して絶対チェックを行いたいと思うでしょう。 if(myfunction($ array、 'field'、 'value')!== FALSE))//何かを行う...
追加された 著者 Andy Cook,

もう一つの解決策は、 array_search()関数に基づいています。 PHP 5.5.0を使用する必要があります以上。

$userdb=Array
(
(0) => Array
    (
        (uid) => '100',
        (name) => 'Sandra Shush',
        (url) => 'urlof100'
    ),

(1) => Array
    (
        (uid) => '5465',
        (name) => 'Stefanie Mcmohn',
        (pic_square) => 'urlof100'
    ),

(2) => Array
    (
        (uid) => '40489',
        (name) => 'Michael',
        (pic_square) => 'urlof40489'
    )
);

$key = array_search(40489, array_column($userdb, 'uid'));

echo ("The key is: ".$key);
//This will output- The key is: 2

説明

関数 array_search()には2つの引数があります。最初のものは検索したい値です。 2番目は、関数が検索する場所です。関数 array_column()は、keyが 'uid' である要素の値を取得します。

Summary

だからあなたはそれを次のように使うことができます:

array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));

または、あなたが好きなら:

// define function
function array_search_multidim($array, $column, $key){
    return (array_search($key, array_column($array, $column)););
}

// use it
array_search_multidim($products, 'slug', 'breville-one-touch-tea-maker-BTM800XL');

The original 例(by xfoxawy) can be found on the DOCS.
The array_column() page.


更新

Vaelのコメントのおかげで、私は興味があったので、 array_search を使用するメソッドのパフォーマンスと、受け入れられた答えで提案されたメソッドを簡単にテストしました。

私は1000個の配列を含む配列を作成しました。構造は次のようになりました(すべてのデータはランダム化されています):

[
      {
            "_id": "57fe684fb22a07039b3f196c",
            "index": 0,
            "guid": "98dd3515-3f1e-4b89-8bb9-103b0d67e613",
            "isActive": true,
            "balance": "$2,372.04",
            "picture": "http://placehold.it/32x32",
            "age": 21,
            "eyeColor": "blue",
            "name": "Green",
            "company": "MIXERS"
      },...
]

I ran the search test 100 times searching for different values for the name field, and then I calculated the mean time in milliseconds. Here you can see an 例.

結果は、この回答で提案された方法は、値を見つけるために約2E-7を必要とし、受け入れられた回答方法は約8E-7を必要とした。

私が前に言ったように、両方の時間は、このサイズの配列を使用するアプリケーションではかなり受け入れられます。サイズが大きくなったら、1Mの要素を考えてみましょう。この小さな違いも増えます。

アップデートⅡ

私は array_walk_recursive に基づいたメソッドのテストを追加しましたが、ここではいくつかの答えについて言及しています。結果は正しいものです。パフォーマンスに重点を置くと、テストで検証された他のパフォーマンスよりも少し劣っています。テストでは、 array_search に基づく方法よりも約10倍遅いことがわかります。ここでも、ほとんどのアプリケーションではこれはあまり意味をなさない違いです。

アップデートIII

@mickmackusaのおかげで、このメソッドのいくつかの制限があります。

  • このメソッドは連想キーで失敗します。
  • このメソッドはインデックス付きサブ配列(0から始まり、連続して昇順キーを持つ)でのみ機能します。
80
追加された
誰もがこれのパフォーマンスを知っていますか?最終的には遅くなり、5.5も必要になるようです。私が5.4にいるように私はテストすることができません。
追加された 著者 Vael Victus,
理解していない人のために:PHP 7では、forループがより速くなります。そのeval.inの例で5.6に変更したとき、array_searchはやや速くなりました。
追加された 著者 Vael Victus,
サブ配列キーが 1 から始まるため、 array_column()array_search()をOPのサンプル配列で使用することはできません。このメソッドは連想キーでも失敗します。このメソッドはインデックス付きサブ配列( 0 から始まり、連続して昇順キーを持つ)でのみ機能します。これは、 array_column()が返される配列に新しいインデックスを生成するためです。
追加された 著者 mickmackusa,
できます!ありがとうmaan $キー= array_search(40489、array_column($ userdb、 'uid'));
追加された 著者 tthreetorch,
まったく正しい@mickmackusa、私は答えにあなたの知識を追加しました。助けてくれてありがとう
追加された 著者 Iván Rodríguez Torre,
賢い! array_column()でarray_combine()を使って、既知のキーでデータを取得する別の配列を作成していますが、もっとエレガントです。
追加された 著者 David,

このクラスメソッドは、複数の条件で配列を検索できます。

class Stdlib_Array
{
    public static function multiSearch(array $array, array $pairs)
    {
        $found = array();
        foreach ($array as $aKey => $aVal) {
            $coincidences = 0;
            foreach ($pairs as $pKey => $pVal) {
                if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) {
                    $coincidences++;
                }
            }
            if ($coincidences == count($pairs)) {
                $found[$aKey] = $aVal;
            }
        }

        return $found;
    }    
}

// Example:

$data = array(
    array('foo' => 'test4', 'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test1', 'bar' => 'baz3'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz4'),
    array('foo' => 'test4', 'bar' => 'baz1'),
    array('foo' => 'test',  'bar' => 'baz1'),
    array('foo' => 'test3', 'bar' => 'baz2'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test4', 'bar' => 'baz1')
);

$result = Stdlib_Array::multiSearch($data, array('foo' => 'test4', 'bar' => 'baz1'));

var_dump($result);

生産する:

array(2) {
  [5]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
  [10]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
}
11
追加された
Hi Fatalist stackoverflow.com/questions/40860030/… それはあなたがその質問を明確にしてくださいこれらの質問にreletedです
追加された 著者 KARTHI SRV,
あなたのソリューションは私の問題を助けました..
追加された 著者 technology_dreamer,

この機能を使用する:

function searchThroughArray($search,array $lists){
try{
    foreach ($lists as $key => $value) {
        if(is_array($value)){
            array_walk_recursive($value, function($v, $k) use($search ,$key,$value,&$val){
                if(strpos($v, $search) !== false )  $val[$key]=$value;
            });
    }else{
            if(strpos($value, $search) !== false )  $val[$key]=$value;
        }

    }
    return $val;

}catch (Exception $e) {
    return false;
}

}

コール機能。

print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));
2
追加された
コードのみの回答は、StackOverflowの値が低いです。リーフノードの部分文字列検索機能がどのように機能するかを説明するためにあなたの投稿を更新してください。この方法は、OPが尋ねているように具体的に機能するようには設計されていないため、違いを明確にすることが重要です。デモリンクを使用すると、読者の理解度が大幅に向上します。常にOPとより多くのSOのオーディエンスを教育するために、回答を投稿してください。
追加された 著者 mickmackusa,
いい答えだ。私の答えにあなたの提案のパフォーマンスをチェックすることができます
追加された 著者 Iván Rodríguez Torre,

次の訪問者が来る場合:再帰的な配列の散歩を使用します。それは多次元配列内のすべての "リーフ"を訪問します。インスピレーションのためにここにあります:

function getMDArrayValueByKey($a, $k) {
    $r = [];
    array_walk_recursive ($a, 
                          function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
                          );
    return $r;
}
1
追加された
@イヴァン・ジョセフの答えはこれとは非常に異なっています。あなた自身でこれをテストしましたか?私はこの答えを目の当たりにしているし、array_walk_recursiveがレベルを見ることができないので、それがうまくいくとは思わない。各第1レベルのキーについて、josefはstrposを呼び出すか、すべてのリーフノードをチェックしています。違いを見ます?
追加された 著者 mickmackusa,
問題ない!あなたの時間を節約するために、josefの答えを試してみると、関数は1つの要素を持つ配列を返します。キーが望ましい答えです:)
追加された 著者 Iván Rodríguez Torre,
もちろん@mickmackusaしかし、ハンスは何かインスピレーションを与えている、答えは文字通り解決策を与えていない。ジョセフが答えてくれたように、より精巧なものが必要です。しかし、あなたはこの答えが問題を完全に解決するわけではないという点では間違いありません。
追加された 著者 Iván Rodríguez Torre,
function search($array, $key, $value) 
{ 
    $results = array(); 

    if (is_array($array)) 
    { 
        if (isset($array[$key]) && $array[$key] == $value) 
            $results[] = $array; 

        foreach ($array as $subarray) 
            $results = array_merge($results, search($subarray, $key, $value)); 
    } 

    return $results; 
} 
1
追加された
コードのみの回答は、StackOverflowの値が低いです。再帰メソッドがどのように機能するか、適切な状況、および再帰が不要なオーバーヘッドである状況を説明するために、あなたの投稿を更新してください。常にOPとより多くのSOのオーディエンスを教育するために、回答を投稿してください。
追加された 著者 mickmackusa,

これを試して

function recursive_array_search($needle,$haystack) {
        foreach($haystack as $key=>$value) {
            $current_key=$key;
            if($needle==$value['uid'] OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
                return $current_key;
            }
        }
        return false;
    }
0
追加された
コードのみの回答は、StackOverflowの値が低いです。再帰メソッドがどのように機能するか、適切な状況、および再帰が不要なオーバーヘッドである状況を説明するために、あなたの投稿を更新してください。常にOPとより多くのSOのオーディエンスを教育するために、回答を投稿してください。 P.S.私はほとんどのPHP開発者があなたの状態で ANDOR の代わりに &&|| current_key を宣言する理由はありません。 $ needle の比較は厳密でなければなりません。
追加された 著者 mickmackusa,

私は以下のようにします。$製品は、最初の問題で与えられた実際の配列です。

print_r(array_search( "breville-variable-temperature-kettle-BKE820XL"、array_map(function($ product){return $ product ["slug"];}、$ products)));

0
追加された
PHP - 日本のコミュニティ [ja]
PHP - 日本のコミュニティ [ja]
4 参加者の

招待状へのリンク: https://t.me/joinchat/B2gdSlA_dh1-BQtEKA2dfw このグループではPHPについて話します。 パートナー:kotaeta.com