Değere göre PHP çok boyutlu dizi araması


332

Ben aramak uidve dizinin anahtarını almak istiyorum bir dizi var .

Örnekler

Aşağıdaki 2 boyutlu diziye sahip olduğumuzu varsayalım:

$userdb = array(
    array(
        'uid' => '100',
        'name' => 'Sandra Shush',
        'pic_square' => 'urlof100'
    ),
    array(
        'uid' => '5465',
        'name' => 'Stefanie Mcmohn',
        'pic_square' => 'urlof100'
    ),
    array(
        'uid' => '40489',
        'name' => 'Michael',
        'pic_square' => 'urlof40489'
    )
);

İşlev çağrısı search_by_uid(100)(ilk kullanıcının uid'i) geri dönmelidir 0.

İşlev çağrısı search_by_uid(40489)geri dönmelidir 2.

Döngüler yapmayı denedim, ancak daha hızlı bir kod yürütmek istiyorum.


ilginç bir şekilde alt çizgi (ve lowdash) kütüphanecileri javascript için bu işlevi eklemek ...
ErichBSchulz

9
Birkaç cevabın performansını test etmek için bir senaryo yazdım. 500k üyeli bir dizi dizisi oluşturur ve bu dizide son üyedeki bir değeri arar. Kabul edilen cevap gibi bir işlevi iki array_columntek katlı cevapla karşılaştırdım . Ben sadece anahtar değil, gerçek keşfedilen dizi dönmek için hepsini değiştirdim, çünkü bu genellikle benim kullanım durumum. Fonksiyon yöntemi, her yöntem için 1000 çalışma üzerinde 0.361, search-col 0.184 ve keys-col 0.189 ortalama mikro gecikme kaydetti.
Josh

Yanıtlar:


474
function searchForId($id, $array) {
   foreach ($array as $key => $val) {
       if ($val['uid'] === $id) {
           return $key;
       }
   }
   return null;
}

Bu çalışacak. Buna şöyle demelisin:

$id = searchForId('100', $userdb);

===Operatör karşılaştırmalı türlerin tam olarak aynı olması gerektiğini bilmek önemlidir , bu örnekte bunun yerine arama yapmanız stringveya sadece kullanmanız gerekir .=====

Dayanarak angoru cevap. PHP'nin ( >= 5.5.0) sonraki sürümlerinde tek astar kullanabilirsiniz.

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

İşte belgeler: http://php.net/manual/en/function.array-column.php .


8
Bunu, PHP 5.5 olmadan, array_column yerine array_map kullanarak tek bir satırda da yapabilmeniz gerekir. Sadece değiştirmek array_column($userdb, 'uid')ilearray_map(function($v){return $v['uid'];},$userdb)
Jesse Yeşil

1
Evet, haklısın. Lambda işlevleri PHP 5.3'ten beri kullanılabilmektedir. ve daha iyisi, array_searchdeğil mi?
Jakub Truneček

@angoru Orijinal çözümün ( foreachdöngü) daha hızlı çalışacağını düşünüyorum çünkü bir eşleşme bulunur bulunmaz durur. Daha yeni çözüm, tüm diziyi bir kez yinelemek array_column, ardından aramayı gerçekleştirmek için ikinci kez döngü yapmak zorundadır (bir eşleşme bulana kadar). Yeni çözümün okunması daha kolay, daha özlü, ancak OP özellikle bir sorun olarak performansı
artırdı

@ JakubTruneček. Soruda verilen aynı dizi ile ilgili bir şey var. Kimlik geçerek diziden kullanıcının adını istiyorum. FindUserName (40489) işlevi 'Michael' döndürmelidir. Nasıl mümkün olabilir?
Ashok Gujjar

@ JakubTruneček Merhaba kodumda bu sorunla karşı karşıya kaldım ama oldukça farklı bir şey var. Benim durumumda 'uid' değeri birden çok kez mevcut yüzden kurulu anahtar dizileri almak gerekir.
Bhavin Thummar

314

(PHP 5> = 5.5.0) kullanıyorsanız, bunu yapmak için kendi işlevinizi yazmak zorunda değilsiniz, sadece bu satırı yazın ve bitti.

Sadece bir sonuç istiyorsanız:

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

Birden çok sonuç için

$keys = array_keys(array_column($userdb, 'uid'), 40489);

Yorumlarda belirtildiği gibi ilişkilendirilebilir bir diziniz varsa, bunu şu şekilde yapabilirsiniz:

$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);

PHP <5.5.0 kullanıyorsanız, bu backport'u kullanabilirsiniz , teşekkürler ramsey!

Güncelleme: Bazı basit ölçütler yapıyorum ve çoklu sonuç formu en hızlı, Jakub özel işlevinden bile daha hızlı görünüyor!


aradığım değer (bu örnekte 40489 ise) bir kereden fazla görünüyorsa ve göründüğü tüm anahtarları almak istiyorum?
Dimitris Papageorgiou

40489 değeri dizide bir kez daha görünürse, işlev bir dizi anahtar döndürür ... ?? @angoru
jishan

Birden fazla sonuç için ikinci vakayı kullanırsanız, bir dizi anahtar alırsınız.
angoru

2
$ Userdb içindeki anahtar 0,1, 2 vb. Olarak başlamamış ve anahtarın 1234,4566 vb. Olduğunu söylerken bu benim için çalışmadı. on
Kaushtuv

1
Bu ilişkisel bir dizi ile çalışmaz, ancak bunun gibi alabilirsiniz: array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
John Mellor

32

PHP'nin sonraki sürümlerinde (> = 5.5.0) bu tek astarı kullanabilirsiniz:

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

Sadece array_column sonucunu dizideki her sonuç için array_column çağrısından kaçınarak belirli bir değişkene koyun.
Maykonn

26

Jakub'un mükemmel cevabını temel alarak, anahtarın belirtilmesine izin verecek daha genel bir arama (sadece kullanıcı kimliği için değil):

function searcharray($value, $key, $array) {
   foreach ($array as $k => $val) {
       if ($val[$key] == $value) {
           return $k;
       }
   }
   return null;
}

Kullanımı: $results = searcharray('searchvalue', searchkey, $array);


Bu çok yararlı, bu çözümü kullanarak sorunumu çözmenin zirvesindeymişim gibi hissediyorum, ancak hala bir sorunum var. Belki fikir verebilir misiniz? Soru burada bulabilirsiniz: stackoverflow.com/questions/28704644/…
jasenmp

19

Bu zaten cevaplanmış olduğunu biliyorum, ama bunu kullandım ve sadece uid tarafından arama yoktu böylece benim kod biraz daha genişletti. Sadece bu işlevselliğe ihtiyaç duyan herkes için paylaşmak istiyorum.

İşte benim örneğim ve lütfen bu ilk cevabım olduğunu unutmayın. Ben sadece belirli bir dizi aramak gerekiyordu çünkü param dizi çıkardı, ama kolayca ekleyebilirsiniz. Ben aslında sadece uid daha fazla aramak istedim.

Ayrıca, benim durumumda, benzersiz olmayan diğer alanlara göre arama sonucunda geri dönmek için birden fazla anahtar olabilir.

 /**
     * @param array multidimensional 
     * @param string value to search for, ie a specific field name like name_first
     * @param string associative key to find it in, ie field_name
     * 
     * @return array keys.
     */
     function search_revisions($dataArray, $search_value, $key_to_search) {
        // This function will search the revisions for a certain value
        // related to the associative key you are looking for.
        $keys = array();
        foreach ($dataArray as $key => $cur_value) {
            if ($cur_value[$key_to_search] == $search_value) {
                $keys[] = $key;
            }
        }
        return $keys;
    }

Daha sonra, başka bir değer ve ilişkisel anahtar aramama izin vermek için bunu yazdım. İlk örneğim, herhangi bir ilişkilendirilebilir anahtarda bir değer aramanıza ve tüm eşleşmeleri döndürmenize izin verir.

Bu ikinci örnek, belirli bir ilişkilendirilebilir anahtarda (ad_adı) bir değerin ('Taylor') nerede bulunduğunu ve başka bir ilişkilendirilebilir anahtarda (kullanılmış) başka bir değer (true) bulunduğunu gösterir ve tüm eşleşmeleri döndürür (Adları olan kişilerin bulunduğu anahtarlar) 'Taylor' AND kullanılır).

/**
 * @param array multidimensional 
 * @param string $search_value The value to search for, ie a specific 'Taylor'
 * @param string $key_to_search The associative key to find it in, ie first_name
 * @param string $other_matching_key The associative key to find in the matches for employed
 * @param string $other_matching_value The value to find in that matching associative key, ie true
 * 
 * @return array keys, ie all the people with the first name 'Taylor' that are employed.
 */
 function search_revisions($dataArray, $search_value, $key_to_search, $other_matching_value = null, $other_matching_key = null) {
    // This function will search the revisions for a certain value
    // related to the associative key you are looking for.
    $keys = array();
    foreach ($dataArray as $key => $cur_value) {
        if ($cur_value[$key_to_search] == $search_value) {
            if (isset($other_matching_key) && isset($other_matching_value)) {
                if ($cur_value[$other_matching_key] == $other_matching_value) {
                    $keys[] = $key;
                }
            } else {
                // I must keep in mind that some searches may have multiple
                // matches and others would not, so leave it open with no continues.
                $keys[] = $key;
            }
        }
    }
    return $keys;
}

İşlev kullanımı

$data = array(
    array(
        'cust_group' => 6,
        'price' => 13.21,
        'price_qty' => 5
    ),
    array(
        'cust_group' => 8,
        'price' => 15.25,
        'price_qty' => 4
    ),
    array(
        'cust_group' => 8,
        'price' => 12.75,
        'price_qty' => 10
    )
);

$findKey = search_revisions($data,'8', 'cust_group', '10', 'price_qty');
print_r($findKey);

Sonuç

Array ( [0] => 2 ) 

10

Array_filter bunun için uygun bir çözüm olacak gibi görünüyor ...

$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'
        )
);

PHP Kodu

<?php 
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
  return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH) // With latest PHP third parameter is mandatory.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY  

$values= print_r(array_value($found)); 
$keys =  print_r(array_keys($found)); 

@BEJAM SHIVA PRASAD bu stackoverflow.com/questions/44721195/… ile bana yardımcı olabilir misiniz ?
Valay

bir hata gösterir:syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ';'
Shihas

Lütfen daha fazla bilgi yapıştırabilir misiniz, yani hangi satır ve kod ve dizi yapısı.
BEJGAM SHIVA PRASAD

@Shihas cevabı güncelledim, çözüleceğinden eminim.
BEJGAM SHIVA PRASAD

9

Array_search açıklama işlevi aşağıdaki örneklerden birini değiştirdim . Fonksiyon searchItemsByKeyçok boyutlu diziden (N seviyeleri) tüm değerleri $ anahtarıyla döndürür. Belki birileri için yararlı olabilir. Misal:

 $arr = array(
     'XXX'=>array(
               'YYY'=> array(
                    'AAA'=> array(
                          'keyN' =>'value1'
                   )
               ),
              'ZZZ'=> array(
                    'BBB'=> array(
                          'keyN' => 'value2'
                   )
               )
              //.....
           )
);


$result = searchItemsByKey($arr,'keyN');

print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
  [0] => value1
  [1] => value2
)

İşlev kodu:

function searchItemsByKey($array, $key)
{
   $results = array();

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

    foreach ($array as $sub_array)
        $results = array_merge($results, searchItemsByKey($sub_array, $key));
  }

 return  $results;
}

7

İşte aynı için bir astar,

$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];

3

Her ne kadar bu eski bir soru ve kabul edilmiş bir cevabı olsa da, kabul edilen cevapta bir değişiklik öneriyorum diye düşündüm .. İlk önce, kabul edilen cevabın burada doğru olduğunu kabul ediyorum.

function searchArrayKeyVal($sKey, $id, $array) {
   foreach ($array as $key => $val) {
       if ($val[$sKey] == $id) {
           return $key;
       }
   }
   return false;
}

Önceden ayarlanmış 'uid' yerine işlevdeki bir parametrenin değiştirilmesi, bu nedenle şimdi aşağıdaki kodu çağırmak, bir işlevi birden çok dizi türünde kullanabileceğiniz anlamına gelir. Küçük bir değişiklik, ama küçük bir fark yaratan bir değişiklik.

    // Array Data Of Users
$userdb = array (
    array ('uid' => '100','name' => 'Sandra Shush','url' => 'urlof100' ),
    array ('uid' => '5465','name' => 'Stefanie Mcmohn','url' => 'urlof100' ),
    array ('uid' => '40489','name' => 'Michael','url' => 'urlof40489' ),
);

// Obtain The Key Of The Array
$arrayKey = searchArrayKeyVal("uid", '100', $userdb);
if ($arrayKey!==false) {
    echo "Search Result: ", $userdb[$arrayKey]['name'];
} else {
    echo "Search Result can not be found";
}

PHP Fiddle Örneği


SOF kullanmanın başka bir nedeni ... Google'a daha kolay ve kendi kodumu veya hatırladığım bir şeyi bulmak .. +1 Kendi genel depom için +1
Angry 84

BTW, sonucu olarak ayarlıyorsunuz nullve sonra kodda, ile karşılaştırıyorsunuz false.
Taha Paksu

Bunun yerine yanlış döndürmeyle düzeltildi, ancak boş değer booleleri kontrol etme durumunda daha iyi olabilir
Angry 84

3

Ben aşağıdaki dizide tha kontrol etmek istiyorum $arralt diziler 'abc' var ya da değil

$arr = array(
    array(
        'title' => 'abc'
    )
);

O zaman bunu kullanabilirim

$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
    echo 'exists';
} else {
    echo 'notExists';
}

Bence bu tanımlamanın en basit yolu


1

Bir dizideki her öğeyi bulur un işlevini kullanmak zorunda kaldı. Bu yüzden Jakub Truneček tarafından yapılan işlevi aşağıdaki gibi değiştirdim:

function search_in_array_r($needle, $array) {
    $found = array();
    foreach ($array as $key => $val) {
        if ($val[1] == $needle) {
            array_push($found, $val[1]);
        }
    }
    if (count($found) != 0)
        return $found;
    else
        return null;
}

1
/**
 * searches a simple as well as multi dimension array
 * @param type $needle
 * @param type $haystack
 * @return boolean
 */
public static function in_array_multi($needle, $haystack){
    $needle = trim($needle);
    if(!is_array($haystack))
        return False;

    foreach($haystack as $key=>$value){
        if(is_array($value)){
            if(self::in_array_multi($needle, $value))
                return True;
            else
               self::in_array_multi($needle, $value);
        }
        else
        if(trim($value) === trim($needle)){//visibility fix//
            error_log("$value === $needle setting visibility to 1 hidden");
            return True;
        }
    }

    return False;
}

1

bu işlevi kullanabilirsiniz; https://github.com/serhatozles/ArrayAdvancedSearch

<?php 
include('ArraySearch.php');

$query = "a='Example World' and b>='2'";

$Array = array(
'a' => array('d' => '2'),
array('a' => 'Example World','b' => '2'),
array('c' => '3'), array('d' => '4'),
);

$Result = ArraySearch($Array,$query,1);

echo '<pre>';
print_r($Result);
echo '</pre>'; 

// Output:
// Array
// (
//    [0] => Array
//        (
//            [a] => Example World
//            [b] => 2
//        )
//
// )

1
$a = ['x' => ['eee', 'ccc'], 'b' => ['zzz']];

$found = null;
$search = 'eee';

array_walk($a, function ($k, $v) use ($search, &$found) {
    if (in_array($search, $k)) {
        $found = $v;
    }
});

var_dump($found);

1

Bunu dene

<?php
 function recursive_array_search($needle,$haystack) {
    foreach($haystack as $key=>$value) {
        $current_key=$key;
        if($needle===$value OR (is_array($value) && 
            recursive_array_search($needle,$value) !== false)) {
             return $current_key;
        }
    }
    return false;
 }
 ?>

1

Sadece paylaş, belki bunu beğenebilirsin.

if( ! function_exists('arraySearchMulti')){
function arraySearchMulti($search,$key,$array,$returnKey=false)
{
    foreach ($array as $k => $val) {
        if (isset($val[$key])) {
            if ((string)$val[$key] == (string)$search) {
                return ($returnKey ? $k : $val);
            }
        }else{
            return (is_array($val) ? arraySearchMulti($search,$key,$val,$returnKey) : null);
        }
    }
    return null;
}}

0

Bunu da dene

function search_in_array($srchvalue, $array)
{
    if (is_array($array) && count($array) > 0)
    {
        $foundkey = array_search($srchvalue, $array);
        if ($foundkey === FALSE)
        {
            foreach ($array as $key => $value)
            {
                if (is_array($value) && count($value) > 0)
                {
                    $foundkey = search_in_array($srchvalue, $value);
                    if ($foundkey != FALSE)
                        return $foundkey;
                }
            }
        }
        else
            return $foundkey;
    }
}

0
for( $i =0; $i < sizeof($allUsers); $i++)
    {   
    $NEEDLE1='firstname';
    $NEEDLE2='emailAddress';
    $sterm='Tofind';
     if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
        {
            $Fname= $allUsers[$i][$NEEDLE1];
            $Lname= $allUsers[$i][$NEEDLE2];

            $pos1 = stripos($Fname, $sterm);
            $pos2=stripos($Lname, $sterm);//not case sensitive 

            if($pos1 !== false ||$pos2 !== false)
            {$resultsMatched[] =$allUsers[$i];}
            else
            {   continue;}              
        }

}
Print_r($resultsMatched); //will give array for matched values even partially matched

Yukarıdaki kod yardımı ile 2D dizisindeki herhangi bir sütundaki herhangi bir (kısmen eşleştirilmiş) veri bulunabilir, böylece kullanıcı kimliği söz konusu şekilde bulunabilir.


Lütfen bunun neden soruya cevap verdiğini açıklamak için bir cümle ekleyin
Lorenz Meyer

Yukarıdaki kodun beyaz yardımı, 2D dizisindeki herhangi bir sütundan herhangi bir (kısmen eşleştirilmiş) veri bulabilir, böylece kullanıcı kimliği söz konusu olduğunda bulunabilir
sandeep sharma

0

@Mayhem tarafından oluşturulan işleve genişleyen bu örnek, yalnızca bir arama dizesinin bir kısmını ( çoğunu ) eşleştirmek istemeniz durumunda daha fazla "bulanık" bir arama olacaktır:

 function searchArrayKeyVal($sKey, $id, $array) {
    foreach ($array as $key => $val) {
        if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
            return $key;
        }
    }
         return false;
 }

Örneğin dizideki değer New York'a Hoş Geldiniz! ve sadece "New York" un ilk örneğini istediniz!


0
$search1 = 'demo';
$search2 = 'bob';
$arr = array('0' => 'hello','1' => 'test','2' => 'john','3' => array('0' => 'martin', '1' => 'bob'),'4' => 'demo');
foreach ($arr as $value) { 
    if (is_array($value)) { 
        if (in_array($search2, $value)) { 
            echo "successsfully";    
            //execute your code 
        }
    } else {  
        if ($value == $search1) { 
            echo "success";
        }
    }
 }

0

Soru yani

$a = [
     [
       "_id" => "5a96933414d48831a41901f2",
       "discount_amount" => 3.29,
       "discount_id" => "5a92656a14d488570c2c44a2",
     ],
     [
       "_id" => "5a9790fd14d48879cf16a9e8",
       "discount_amount" => 4.53,
       "discount_id" => "5a9265b914d488548513b122",
     ],
     [
       "_id" => "5a98083614d488191304b6c3",
       "discount_amount" => 15.24,
       "discount_id" => "5a92806a14d48858ff5c2ec3",
     ],
     [
       "_id" => "5a982a4914d48824721eafe3",
       "discount_amount" => 45.74,
       "discount_id" => "5a928ce414d488609e73b443",
     ],
    [
       "_id" => "5a982a4914d48824721eafe55",
       "discount_amount" => 10.26,
       "discount_id" => "5a928ce414d488609e73b443",
     ],
   ];

Ans:

function searchForId($id, $array) {
    $did=0;
    $dia=0;
   foreach ($array as $key => $val) {
       if ($val['discount_id'] === $id) {
           $dia +=$val['discount_amount'];
           $did++;
       }
   }
    if($dia != '') {
        echo $dia;
        var_dump($did);
    }
   return null;
};
print_r(searchForId('5a928ce414d488609e73b443',$a));

0

çözümüm:

function searchArrayForField($array, $field, $value) {
    $i = 0;
    foreach ($array as &$row) {
        if ($row[$field] === $value) {
            return $i;
        }
        $i++
    }
    return '';
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.