Búsqueda de matriz multidimensional de PHP por valor

332

Tengo una matriz donde quiero buscar uidy obtener la clave de la matriz.

Ejemplos

Supongamos que tenemos la siguiente matriz bidimensional:

$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 llamada a la función search_by_uid(100)(uid del primer usuario) debería regresar 0.

La llamada a la función search_by_uid(40489)debería regresar 2.

Intenté hacer bucles, pero quiero un código de ejecución más rápido.

Rachit
fuente
Curiosamente, los bibliotecarios de subrayado (y lowdash) agregan esta función a JavaScript ...
ErichBSchulz
99
Escribí un guión para probar el rendimiento de algunas de las respuestas. Genera una matriz de matrices de 500k miembros y busca a través de ella un valor en el último miembro. Comparé una función como la respuesta aceptada, con las dos array_columnrespuestas de una línea. Los modifiqué todos para devolver la matriz descubierta real, no solo la clave, porque generalmente ese es mi caso de uso. El método de función obtuvo 0.361, search-col 0.184 y keys-col 0.189 micro micro delay en 1000 ejecuciones para cada método.
Josh

Respuestas:

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

Esto funcionará Deberías llamarlo así:

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

Es importante saber que si está utilizando ===operadores, los tipos comparados tienen que ser exactamente iguales, en este ejemplo, debe buscar stringo simplemente usar ==en su lugar ===.

Basado en la respuesta de angoru . En versiones posteriores de PHP ( >= 5.5.0) puede usar one-liner.

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

Aquí hay documentación: http://php.net/manual/en/function.array-column.php .

Jakub Truneček
fuente
8
También debería poder hacer esto sin PHP 5.5 en una línea usando array_map en lugar de array_column. Simplemente reemplace array_column($userdb, 'uid')conarray_map(function($v){return $v['uid'];},$userdb)
Jesse Green
1
Sí, tienes razón. Las funciones de Lambda están disponibles desde PHP 5.3. y mejor es array_search, ¿no?
Jakub Truneček
@angoru Creo que la solución original (el foreachbucle) funcionará más rápido porque se detiene tan pronto como se encuentre una coincidencia. La solución más nueva tiene que iterar a través de toda la matriz una vez para extraer array_column, luego recorrerla por segunda vez para realizar la búsqueda (hasta que encuentre una coincidencia). La solución más nueva es más fácil de leer, más concisa, pero el OP mencionó específicamente el rendimiento como un problema
BeetleJuice el
@ JakubTruneček. Tengo algo que ver con la misma matriz dada en la pregunta. Quiero el nombre de usuario de la matriz pasando id. La función findUserName (40489) debería devolver 'Michael'. ¿Como es posible?
Ashok Gujjar
@ JakubTruneček Hola, he enfrentado este problema en mi código, pero tengo algo muy diferente. En mi caso, el valor 'uid' está presente varias veces, así que necesito obtener una matriz de clave fundada.
Bhavin Thummar
314

Si está utilizando (PHP 5> = 5.5.0) no tiene que escribir su propia función para hacerlo, simplemente escriba esta línea y ya está.

Si solo quieres un resultado:

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

Para múltiples resultados

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

En caso de que tenga una matriz asociativa como se señala en los comentarios, puede hacerlo con:

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

Si está utilizando PHP <5.5.0, puede usar este backport , ¡gracias ramsey!

Actualización: He estado haciendo algunos puntos de referencia simples y el formulario de resultados múltiples parece ser el más rápido, ¡incluso más rápido que la función personalizada de Jakub!

angoru
fuente
¿Qué pasa si el valor que estoy buscando (en este ejemplo es 40489) aparece más de una vez y quiero obtener todas las claves que aparece?
Dimitris Papageorgiou
si el valor 40489 aparece más de una vez en la matriz, ¿la función devolverá una matriz de teclas ...? @angoru
jishan
Si usa el segundo caso para obtener múltiples resultados, obtendrá una matriz de claves.
angoru
2
Esto no funcionó para mí cuando la clave en $ userdb no comenzó como 0,1, 2, etc. y dice que la clave es 1234,4566, etc. Las claves resultantes después de array_search son siempre 0,1,2 y así en
Kaushtuv
1
Esto no funcionará con una matriz asociativa, sin embargo, puede solucionarlo así: array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
John Mellor
32

En versiones posteriores de PHP (> = 5.5.0) puede usar esta línea:

$key = array_search('100', array_column($userdb, 'uid'));
Iryna Batvina
fuente
Simplemente coloque el resultado de array_column en una variable específica evitando que se llame a array_column para cada resultado en la matriz.
Maykonn
26

Aprovechando la excelente respuesta de Jakub , aquí hay una búsqueda más generalizada que permitirá especificar la clave (no solo para uid):

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

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

reflexiv
fuente
Esto es muy útil, siento que estoy a punto de resolver mi problema usando esta solución, pero todavía tengo algunos problemas. ¿Podrías quizás darnos una idea? La pregunta se puede encontrar aquí: stackoverflow.com/questions/28704644/…
jasenmp
19

Sé que esto ya fue respondido, pero lo usé y lo extendí un poco más en mi código para que no tuviera que buscar solo el uid. Solo quiero compartirlo con cualquier otra persona que pueda necesitar esa funcionalidad.

Aquí está mi ejemplo y tenga en cuenta que esta es mi primera respuesta. Saqué la matriz param porque solo necesitaba buscar una matriz específica, pero podía agregarla fácilmente. Quería buscar esencialmente más que solo el uid.

Además, en mi situación, puede haber varias claves para devolver como resultado de la búsqueda por otros campos que pueden no ser únicos.

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

Más tarde, terminé escribiendo esto para permitirme buscar otro valor y clave asociativa. Entonces, mi primer ejemplo le permite buscar un valor en cualquier clave asociativa específica y devolver todas las coincidencias.

Este segundo ejemplo muestra dónde se encuentra un valor ('Taylor') en una determinada clave asociativa (nombre_nombre) Y otro valor (verdadero) se encuentra en otra clave asociativa (empleada), y devuelve todas las coincidencias (Claves donde las personas con nombre 'Taylor' Y son empleados).

/**
 * @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 de la función

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

Resultado

Array ( [0] => 2 ) 
amurrell
fuente
10

Parece que array_filter será la solución adecuada para esto ...

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

Código 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
fuente
@BEJAM SHIVA PRASAD, ¿podría ayudarme con este stackoverflow.com/questions/44721195/… ?
Valay
muestra un error:syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ';'
Shihas
¿Puede pegar más información? Quiero decir qué línea y su código y estructura de matriz.
BEJGAM SHIVA PRASAD
@Shi ha actualizado la respuesta, estoy seguro de que se resolverá.
BEJGAM SHIVA PRASAD
9

Modifiqué uno de los ejemplos debajo de la función de descripción array_search . La función searchItemsByKeydevuelve todos los valores por $ clave de la matriz multidimensional (N niveles). Tal vez, sería útil para alguien. Ejemplo:

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

Código de función:

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

Aquí hay un revestimiento para lo mismo,

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

Aunque esta es una pregunta antigua y tiene una respuesta aceptada, pensé que sugeriría un cambio a la respuesta aceptada. Entonces, en primer lugar, estoy de acuerdo en que la respuesta aceptada es correcta aquí.

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

En su lugar, reemplazar el 'uid' preestablecido con un parámetro en la función, por lo que ahora llamar al código siguiente significa que puede usar una función en múltiples tipos de matriz. Pequeño cambio, pero uno que hace la ligera diferencia.

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

Ejemplo de violín PHP

Enojado 84
fuente
Otra razón por la que uso SOF ... es más fácil buscar en Google y encontrar mi propio código o algo que recuerdo ... +1 para mi propio repositorio público
Angry 84
Por cierto, está configurando el resultado nully luego, en el código, lo está comparando false.
Taha Paksu
En su lugar, se corrigió devolviendo falso, pero nulo podría ser mejor en caso de verificar booleanos
enojado 84
3

Quiero comprobar que en la siguiente matriz $arrhay 'abc' existe en sub matrices o no

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

Entonces puedo usar esto

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

Creo que esta es la forma más sencilla de definir

M.suleman Khan
fuente
1

Tuve que usar una función que encuentra todos los elementos en una matriz. Así que modifiqué la función realizada por Jakub Truneček de la siguiente manera:

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
fuente
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
fuente
1

puedes usar esta función; 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
fuente
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
fuente
1

Prueba esto

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

Solo comparte, tal vez me guste esto.

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
fuente
0

Prueba esto también

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;
    }
}
PravinS
fuente
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 la ayuda del código anterior, se pueden encontrar los datos (parcialmente coincidentes) de cualquier columna en la matriz 2D para que la identificación del usuario se pueda encontrar según sea necesario.

sandeep sharma
fuente
Agregue una frase para explicar por qué esto responde la pregunta
Lorenz Meyer
whit ayuda de código de seguridad se pueden encontrar los datos (parcialmente emparejado) de cualquier columna de matriz 2D así ID de usuario se puede encontrar como se requiere en cuestión
Sandeep Sharma
0

Ampliando la función que @mayhem creó, este ejemplo sería más una búsqueda "difusa" en caso de que solo desee hacer coincidir parte (la mayoría ) de una cadena de búsqueda:

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

Por ejemplo, el valor en la matriz es ¡Bienvenido a Nueva York! y querías la primera instancia de "¡Nueva York!"

Mike Q
fuente
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
fuente
0

Si la pregunta es decir

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

Respuesta:

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
fuente
0

mi solución:

function searchArrayForField($array, $field, $value) {
    $i = 0;
    foreach ($array as &$row) {
        if ($row[$field] === $value) {
            return $i;
        }
        $i++
    }
    return '';
}
costamatrix
fuente