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.


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 .


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!


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

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


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 ) 

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

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

7

Oto jedna wkładka do tego samego,

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

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


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


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

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

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

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

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

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

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

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.


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!”


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

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

0

moje rozwiązanie:

function searchArrayForField($array, $field, $value) {
    $i = 0;
    foreach ($array as &$row) {
        if ($row[$field] === $value) {
            return $i;
        }
        $i++
    }
    return '';
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.