PHP wielowymiarowe wyszukiwanie tablic według wartości

332

Mam tablicę, w której chcę wyszukać uidi uzyskać klucz tablicy.

Przykłady

Załóżmy, że mamy następującą dwuwymiarową tablicę:

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

Wywołanie funkcji search_by_uid(100)(identyfikator pierwszego użytkownika) powinno zostać zwrócone 0.

Wywołanie funkcji search_by_uid(40489)powinno wrócić 2.

Próbowałem tworzyć pętle, ale chcę szybciej wykonywać kod.

Rachit
źródło
co ciekawe, biblioteki podkreślenia (i lowdash) dodają tę funkcję do javascript ...
ErichBSchulz
9
Napisałem skrypt, aby przetestować działanie kilku odpowiedzi. Generuje tablicę zawierającą 500 000 elementów i przeszukuje ją w celu znalezienia wartości w ostatnim elemencie. Porównałem funkcję taką jak zaakceptowana odpowiedź z dwiema array_columnodpowiedziami jednowierszowymi. Zmodyfikowałem je wszystkie, aby zwracały faktycznie wykrytą tablicę, a nie tylko klucz, ponieważ zwykle taki jest mój przypadek użycia. Metoda funkcji uzyskała wynik 0,361, kolumna wyszukiwania 0,184 i kolumna 0,189 średniego mikro opóźnienia dla 1000 metod dla każdej metody.
Josh

Odpowiedzi:

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

To zadziała. Powinieneś to tak nazwać:

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

Ważne jest, aby wiedzieć, że jeśli używasz ===operatora porównaniu typy muszą być dokładnie takie same, w tym przypadku trzeba szukać stringlub po prostu użyć ==zamiast ===.

Na podstawie odpowiedzi angoru . W późniejszych wersjach PHP ( >= 5.5.0) możesz używać jednej linijki.

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

Oto dokumentacja: http://php.net/manual/en/function.array-column.php .

Jakub Truneček
źródło
8
Powinieneś być również w stanie to zrobić bez PHP 5.5 w jednej linijce, używając array_map zamiast array_column. Wystarczy wymienić array_column($userdb, 'uid')zarray_map(function($v){return $v['uid'];},$userdb)
Jesse Zielona
1
Masz rację. Funkcje Lambda są dostępne od PHP 5.3. i lepiej array_search, prawda?
Jakub Truneček
@angoru Myślę, że oryginalne rozwiązanie ( foreachpętla) będzie działać szybciej, ponieważ zatrzymuje się, gdy tylko zostanie znalezione dopasowanie. Nowsze rozwiązanie musi raz wykonać iterację przez całą tablicę, aby ją wyodrębnić array_column, a następnie zapętlić ją po raz drugi, aby wykonać wyszukiwanie (dopóki nie znajdzie pasującego elementu). Nowsze rozwiązanie jest łatwiejsze do odczytania, bardziej zwięzłe, ale OP specjalnie podniosło wydajność jako problem
BeetleJuice
@ JakubTruneček. Mam coś wspólnego z tą samą tablicą podaną w pytaniu. Chcę nazwę użytkownika z tablicy, przekazując identyfikator. Funkcja findUserName (40489) powinna zwracać „Michael”. Jak to możliwe?
Ashok Gujjar
@ JakubTruneček Cześć. W moim kodzie napotkałem ten problem, ale mam coś zupełnie innego. W moim przypadku wartość „UID” występuje wiele razy, więc muszę uzyskać tablice założonego klucza.
Bhavin Thummar,
314

Jeśli używasz (PHP 5> = 5.5.0), nie musisz pisać własnej funkcji, aby to zrobić, po prostu napisz ten wiersz i gotowe.

Jeśli chcesz tylko jeden wynik:

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

Aby uzyskać wiele wyników

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

Jeśli masz tablicę asocjacyjną, jak wskazano w komentarzach, możesz to zrobić za pomocą:

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

Jeśli używasz PHP <5.5.0, możesz użyć tego backportu , dzięki ramsey!

Aktualizacja: Wykonałem kilka prostych testów porównawczych, a formularz wielu wyników wydaje się najszybszy, nawet szybszy niż niestandardowa funkcja Jakuba!

angoru
źródło
co jeśli wartość, której szukam (w tym przykładzie jest 40489) pojawia się więcej niż jeden raz i chcę uzyskać wszystkie klucze, które się pojawiają?
Dimitris Papageorgiou
jeśli wartość 40489 pojawi się więcej niż raz w tablicy, funkcja zwróci tablicę kluczy ... ?? @angoru
jishan
Jeśli użyjesz drugiego przypadku do wielu wyników, otrzymasz tablicę kluczy.
angoru
2
Nie działało to dla mnie, gdy klucz w $ userdb nie zaczął się jako 0,1, 2 itd. I powiedzmy, że klucz to 1234,4566 itd. Klucze wynikowe po przeszukiwaniu tablicy są zawsze 0,1,2 i tak on
Kaushtuv
1
To nie zadziała z tablicą asocjacyjną, jednak można to obejść w następujący sposób: array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
John Mellor
32

W późniejszych wersjach PHP (> = 5.5.0) możesz użyć tego jednowierszowego:

$key = array_search('100', array_column($userdb, 'uid'));
Iryna Batvina
źródło
Wystarczy umieścić wynik kolumna_kolumny w określonej zmiennej, unikając wywołania kolumny_kolumny dla każdego wyniku w tablicy.
Maykonn
26

Opierając się na doskonałej odpowiedzi Jakuba , oto bardziej ogólne wyszukiwanie, które pozwoli określić klucz (nie tylko identyfikator użytkownika):

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

Stosowanie: $results = searcharray('searchvalue', searchkey, $array);

reflexiv
źródło
Jest to bardzo pomocne, wydaje mi się, że jestem bliski rozwiązania mojego problemu za pomocą tego rozwiązania, ale nadal mam problem. Czy mógłbyś podać wgląd? Pytanie można znaleźć tutaj: stackoverflow.com/questions/28704644/…
jasenmp
19

Wiem, że już na nie odpowiedziano, ale użyłem tego i rozszerzyłem go trochę w moim kodzie, abyś nie szukał tylko identyfikatora użytkownika. Chcę go tylko udostępnić każdemu, kto może potrzebować tej funkcji.

Oto mój przykład i proszę pamiętać, że to moja pierwsza odpowiedź. Wyjąłem tablicę parametrów, ponieważ musiałem przeszukać tylko jedną konkretną tablicę, ale można ją łatwo dodać. Chciałem zasadniczo wyszukać coś więcej niż tylko identyfikator użytkownika.

Ponadto w mojej sytuacji może być wiele kluczy do zwrócenia w wyniku wyszukiwania według innych pól, które mogą nie być unikalne.

 /**
     * @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;
    }

Później skończyłem pisać to, aby pozwolić mi szukać innej wartości i klucza asocjacyjnego. Tak więc mój pierwszy przykład pozwala wyszukać wartość w dowolnym kluczu asocjacyjnym i zwrócić wszystkie dopasowania.

Ten drugi przykład pokazuje, gdzie wartość („Taylor”) znajduje się w pewnym kluczu asocjacyjnym (imię), ORAZ inną wartość (true) znajduje się w innym kluczu asocjacyjnym (zatrudniony), i zwraca wszystkie dopasowania (klucze, w których ludzie o imieniu „Taylor” AND jest zatrudniony).

/**
 * @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;
}

Zastosowanie funkcji

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

Wynik

Array ( [0] => 2 ) 
amurrell
źródło
10

Wygląda, że array_filter będzie odpowiednim rozwiązaniem dla tego ...

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

Kod PHP

<?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)); 
BEJGAM SHIVA PRASAD
źródło
@BEJAM SHIVA PRASAD, czy mógłbyś mi pomóc z tym stackoverflow.com/questions/44721195/... ?
Valay
pokazuje błąd:syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ';'
Shihas,
Czy możesz wkleić więcej informacji Mam na myśli to, która linia oraz twój kod i struktura tablicy.
BEJGAM SHIVA PRASAD
@Shihas Zaktualizowałem odpowiedź, jestem pewien, że zostanie rozwiązana.
BEJGAM SHIVA PRASAD
9

Zmodyfikowałem jeden z poniższych przykładów funkcji tablica_wyszukiwania . Funkcja searchItemsByKeyzwraca wszystkie wartości według klucza $ z tablicy wielowymiarowej (N poziomów). Być może przydałby się komuś. Przykład:

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

Kod funkcji:

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;
}
voodoo417
źródło
7

Oto jedna wkładka do tego samego,

$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];
Rahul
źródło
3

Mimo że jest to stare pytanie i ma zaakceptowaną odpowiedź, pomyślałem, że zasugeruję jedną zmianę w zaakceptowanej odpowiedzi. Po pierwsze, zgadzam się, że zaakceptowana odpowiedź jest tutaj poprawna.

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

Zastąpienie wstępnie ustawionego „uid” parametrem w funkcji, więc teraz wywołanie poniższego kodu oznacza, że ​​możesz używać jednej funkcji w wielu typach tablic. Mała zmiana, ale taka, która robi niewielką różnicę.

    // 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";
}

Przykład PHP Fiddle

Zły 84
źródło
Kolejny powód, dla którego używam SOF ... łatwiej wyszukiwać w Google i znaleźć własny kod lub coś, co pamiętam .. +1 dla mojego publicznego repozytorium
Zły 84
BTW, ustawiasz wynik, nulla następnie w kodzie, porównujesz go false.
Taha Paksu,
Poprawiono zamiast zwracania wartości false, ale wartość null może być lepsza w przypadku sprawdzania wartości logicznych
Angry 84
3

Chcę sprawdzić, czy w poniższej tablicy $arrjest „abc” w podtablicach, czy nie

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

Potem mogę tego użyć

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

Myślę, że to najprostszy sposób na zdefiniowanie

M.suleman Khan
źródło
1

Musiałem użyć funkcji un, która znajduje wszystkie elementy w tablicy. Zmodyfikowałem więc funkcję wykonaną przez Jakuba Trunečka w następujący sposób:

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;
}
csi_bern
źródło
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;
}
Ahad Ali
źródło
1

możesz użyć tej funkcji; 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
//        )
//
// )
Serhat
źródło
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);
serghei
źródło
1

Spróbuj tego

<?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;
 }
 ?>
Maurizio Ricci
źródło
1

Po prostu udostępnij, może ci się spodoba.

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;
}}
Whendy Takashy
źródło
0

Spróbuj tego również

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;
    }
}
Prawdy
źródło
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

Za pomocą powyższego kodu można znaleźć dowolne (częściowo dopasowane) dane z dowolnej kolumny w tablicy 2D, dzięki czemu można znaleźć identyfikator użytkownika zgodnie z wymaganiami.

sandeep sharma
źródło
Dodaj frazę, aby wyjaśnić, dlaczego to odpowiada na pytanie
Lorenz Meyer
przy pomocy powyższego kodu można znaleźć dowolne (częściowo dopasowane) dane z dowolnej kolumny w tablicy 2D, dzięki czemu można znaleźć identyfikator użytkownika zgodnie z wymaganiami w pytaniu
sandeep sharma
0

Rozwijając utworzoną funkcję @mayhem, ten przykład byłby bardziej „rozmytym” wyszukiwaniem w przypadku, gdybyś chciał dopasować tylko część ( większość ) ciągu wyszukiwania:

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

Na przykład wartość w tablicy to Welcome to New York! i chciałeś pierwszego wystąpienia po prostu „New York!”

Mike Q
źródło
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";
        }
    }
 }
Bhavyesh
źródło
0

Jeśli pytanie tj

$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",
     ],
   ];

Odp .:

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));
Yuvraj Singh Shekhawat
źródło
0

moje rozwiązanie:

function searchArrayForField($array, $field, $value) {
    $i = 0;
    foreach ($array as &$row) {
        if ($row[$field] === $value) {
            return $i;
        }
        $i++
    }
    return '';
}
costamatrix
źródło