Ricerca di array multidimensionali PHP per valore


332

Ho un array in cui voglio cercare uid e ottenere la chiave dell'array.

Esempi

Supponiamo di avere il seguente array bidimensionale:

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

La chiamata di funzione search_by_uid(100)(utente del primo utente) dovrebbe tornare 0.

La chiamata di funzione search_by_uid(40489)dovrebbe tornare2 .

Ho provato a creare loop, ma voglio un codice di esecuzione più veloce.


interessante notare che le librerie underscore (e lowdash) aggiungono questa funzione a javascript ...
ErichBSchulz

9
Ho scritto una sceneggiatura per testare le prestazioni di alcune risposte. Genera una matrice di array da 500k membri e cerca in esso un valore nell'ultimo membro. Ho confrontato una funzione come la risposta accettata, con le due array_columnrisposte a una riga. Li ho modificati tutti per restituire l'array scoperto effettivo, non solo la chiave, perché di solito è il mio caso d'uso. Il metodo di funzione ha ottenuto 0,361, ricerca-col 0,184 e chiavi-col 0,189 micro ritardo medio su 1000 corse per ciascun metodo.
Josh,

Risposte:


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

Questo funzionerà. Dovresti chiamarlo così:

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

È importante sapere che se si utilizzano ===tipi di operatore confrontati devono essere esattamente gli stessi, in questo esempio è necessario cercare stringo semplicemente utilizzare ==invece ===.

Basato sulla risposta angoru . Nelle versioni successive di PHP ( >= 5.5.0) è possibile utilizzare one-liner.

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

Ecco la documentazione: http://php.net/manual/en/function.array-column.php .


8
Dovresti anche essere in grado di farlo senza PHP 5.5 in una riga usando array_map al posto di array_column. Basta sostituire array_column($userdb, 'uid')conarray_map(function($v){return $v['uid'];},$userdb)
Jesse Green il

1
Sì, hai ragione. Le funzioni Lambda sono disponibili da PHP 5.3. e meglio è array_search, no?
Jakub Truneček,

@angoru Penso che la soluzione originale (il foreachloop) funzionerà più velocemente perché si interrompe non appena viene trovata una corrispondenza. La soluzione più recente deve scorrere una volta per estrarre l'intero array array_column, quindi scorrere una seconda volta per eseguire la ricerca (fino a quando non trova una corrispondenza). La soluzione più recente è più facile da leggere, più concisa, ma l'OP ha sollevato in modo specifico le prestazioni come un problema
BeetleJuice

@ JakubTruneček. Ho qualcosa a che fare con lo stesso array indicato nella domanda. Voglio il nome dell'utente dall'array passando id. La funzione findUserName (40489) dovrebbe restituire "Michael". Com'è possibile?
Ashok Gujjar

@ JakubTruneček Ciao, ho riscontrato questo problema nel mio codice ma ho una cosa abbastanza diversa. Nel mio caso il valore "uid" è presente più volte, quindi ho bisogno di ottenere una matrice di chiavi fondate.
Bhavin Thummar

314

Se stai usando (PHP 5> = 5.5.0) non devi scrivere la tua funzione per farlo, basta scrivere questa riga e il gioco è fatto.

Se vuoi un solo risultato:

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

Per più risultati

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

Nel caso in cui tu abbia un array associativo come indicato nei commenti puoi farlo con:

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

Se si utilizza PHP <5.5.0, è possibile utilizzare questo backport , grazie ramsey!

Aggiornamento: sto realizzando alcuni semplici benchmark e il modulo per risultati multipli sembra essere il più veloce, anche più veloce della funzione personalizzata Jakub!


cosa succede se il valore che sto cercando (in questo esempio è 40489) appare più di una volta e voglio ottenere tutte le chiavi che appare?
Dimitris Papageorgiou,

se il valore 40489 appare più di una volta nell'array la funzione restituirà una matrice di chiavi ... ?? @angoru
jishan,

Se si utilizza il secondo caso per più risultati, si ottiene una matrice di chiavi.
Angoru,

2
Questo non ha funzionato per me quando la chiave in $ userdb non è iniziata come 0,1, 2 ecc. E diciamo che la chiave è 1234,4566 ecc. Le chiavi risultanti dopo array_search sono sempre 0,1,2 e così on
Kaushtuv,

1
Questo non funzionerà con un array associativo, tuttavia puoi aggirarlo in questo modo: array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
John Mellor

32

Nelle versioni successive di PHP (> = 5.5.0) è possibile utilizzare questo one-liner:

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

Basta inserire il risultato array_column in una variabile specifica evitando di chiamare array_column per ogni risultato sull'array.
Maykonn,

26

Costruendo l' eccellente risposta di Jakub , ecco una ricerca più generalizzata che consentirà di specificare la chiave (non solo per l'utente):

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

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


Questo è molto utile, mi sento come se fossi sulla cuspide di risolvere il mio problema usando questa soluzione ma sto ancora riscontrando qualche problema. Potresti forse fornire informazioni? La domanda può essere trovata qui: stackoverflow.com/questions/28704644/...
jasenmp

19

So che è già stata data una risposta, ma l'ho usato e l'ho esteso un po 'di più nel mio codice in modo che tu non avessi cercato solo dall'UID. Voglio solo condividerlo per chiunque altro abbia bisogno di tale funzionalità.

Ecco il mio esempio e tieni a mente che questa è la mia prima risposta. Ho eliminato l'array param perché avevo solo bisogno di cercare un array specifico, ma potevi facilmente aggiungerlo. Volevo essenzialmente cercare più di un semplice uid.

Inoltre, nella mia situazione potrebbero esserci più chiavi da restituire a seguito della ricerca in altri campi che potrebbero non essere univoche.

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

Più tardi, ho finito per scrivere questo per permettermi di cercare un altro valore e chiave associativa. Quindi il mio primo esempio ti consente di cercare un valore in qualsiasi chiave associativa specifica e restituire tutte le corrispondenze.

Questo secondo esempio mostra dove si trova un valore ("Taylor") in una determinata chiave associativa (first_name) E un altro valore (true) viene trovato in un'altra chiave associativa (utilizzata) e restituisce tutte le corrispondenze (chiavi in ​​cui le persone con nome 'Taylor' AND sono impiegati).

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

Uso della funzione

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

Risultato

Array ( [0] => 2 ) 

10

Sembra array_filter sarà la soluzione adatta per questo ...

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

Codice 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 potresti per favore aiutarmi con questo stackoverflow.com/questions/44721195/… ?
Valay,

mostra un errore:syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ';'
Shihas

Potete per favore incollare più informazioni, intendo quale linea, il codice e la struttura dell'array.
BEJGAM SHIVA PRASAD,

@Shiha ho aggiornato la risposta, sono sicuro che verrà risolto.
BEJGAM SHIVA PRASAD

9

Ho modificato uno degli esempi sotto la descrizione della funzione array_search . La funzione searchItemsByKeyrestituisce tutti i valori per $ chiave dall'array multidimensionale (N livelli). Forse sarebbe utile per qualcuno. Esempio:

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

Codice funzione:

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

Ecco una fodera per lo stesso,

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

3

Anche se questa è una vecchia domanda e ha una risposta accettata, ho pensato di suggerire una modifica alla risposta accettata. Quindi, prima di tutto, sono d'accordo che la risposta accettata è corretta qui.

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

Sostituendo il 'uid' preimpostato con un parametro nella funzione, quindi ora chiamare il codice seguente significa che è possibile utilizzare una funzione su più tipi di array. Piccolo cambiamento, ma uno che fa la leggera differenza.

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

Esempio di violino PHP


Un altro motivo per cui utilizzo SOF ... più facile per google e trovare il mio codice o qualcosa che ricordo .. +1 per il mio repository pubblico
Angry 84

A proposito, stai impostando il risultato su nulle poi nel codice, lo stai confrontando false.
Taha Paksu,

Corretto con la restituzione di false, invece, null potrebbe essere meglio in caso di controllo di booleani
Angry 84

3

Voglio verificare che nel seguente array $arrci sia o meno "abc" negli array secondari

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

Quindi posso usare questo

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

Penso che questo sia il modo più semplice per definire


1

Ho dovuto usare una funzione che trova tutti gli elementi in un array. Quindi ho modificato la funzione svolta da Jakub Truneček come segue:

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

puoi usare questa funzione; 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

Prova questo

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

Basta condividere, forse può piacere così.

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

Prova anche questo

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

Con l'aiuto del codice sopra si possono trovare tutti i dati (parzialmente abbinati) da qualsiasi colonna nell'array 2D in modo che l'id utente possa essere trovato come richiesto in questione.


Per favore, aggiungi una frase per spiegare perché questo risponde alla domanda
Lorenz Meyer,

con l'aiuto del codice sopra si possono trovare tutti i dati (parzialmente corrispondenti) da qualsiasi colonna nell'array 2D in modo da poter trovare l'id utente come richiesto nella domanda
sandeep sharma,

0

Espandendo la funzione creata da @mayhem, questo esempio sarebbe più di una ricerca "fuzzy" nel caso in cui si desideri solo far corrispondere la parte (la maggior parte ) di una stringa di ricerca:

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

Ad esempio, il valore nella matrice è Benvenuti a New York! e volevi la prima istanza di "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

Se domanda cioè

$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

la mia soluzione:

function searchArrayForField($array, $field, $value) {
    $i = 0;
    foreach ($array as &$row) {
        if ($row[$field] === $value) {
            return $i;
        }
        $i++
    }
    return '';
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.