2009-05-13 18 views

Respuesta

25

Si tiene una matriz 2D, como en el ejemplo, que necesita para personalizar las cosas un poco:

function array_search2d($needle, $haystack) { 
    for ($i = 0, $l = count($haystack); $i < $l; ++$i) { 
     if (in_array($needle, $haystack[$i])) return $i; 
    } 
    return false; 
} 

$myArray = array(
    array('username' => 'user1'), 
    array('username' => 'user2') 
); 
$searchTerm = "user1"; 

if (false !== ($pos = array_search2d($searchTerm, $myArray))) { 
    echo $searchTerm . " found at index " . $pos; 
} else { 
    echo "Could not find " . $searchTerm; 
} 

Si quería busque en un solo campo en particular, puede modificar la función a algo como esto:

function array_search2d_by_field($needle, $haystack, $field) { 
    foreach ($haystack as $index => $innerArray) { 
     if (isset($innerArray[$field]) && $innerArray[$field] === $needle) { 
      return $index; 
     } 
    } 
    return false; 
} 
+2

En lugar de iterar la matriz con el bucle for/count, ¿por qué no "foreach ($ haystack as $ key => $ value)"? También, esto encontraría "user1" en cualquier campo, no solo "username" – gnarf

+0

Oh. El PO fue un poco ambiguo sobre ese aspecto del problema. Editaré ahora – nickf

+0

Muy buena solución +1 – nikhil

27

Eche un vistazo a array_search.

Desde el archivo PHP ayuda:

<?php 
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red'); 

$key = array_search('green', $array); // $key = 2; 
$key = array_search('red', $array); // $key = 1; 
?> 
+2

esto no funcionará para él, ya que tiene una matriz 2D. sin embargo ... ha sido aceptado, extrañamente. – nickf

+0

Sí, lo siento, lo acepté demasiado pronto. ¿Alguna idea sobre cómo hacerlo con una matriz 2D? – roflwaffle

+1

@nickf, en realidad responde al título de la pregunta, pensó que de hecho no respondía el cuerpo de la pregunta. –

2

Quizás usando array_filter y array_keys juntos ayudarán.

Enfoque basado en la clase.

<?php 

class ArraySearch2d { 
    static protected $_key; 
    static protected $_value; 

    static function isMatch($element) 
    { 
    if (!is_array($element)) return false; 
    return $element[self::$_key] == self::$_value; 
    } 

    static function filter(array $arrayToSearch, $key, $value) 
    { 
    if (!is_string($key)) throw new Exception("Array Key must be a string"); 
    self::$_key = $key; 
    self::$_value = $value; 
    return array_filter($arrayToSearch, 'ArraySearch2d::isMatch'); 
    } 

    // to directly answer your question. 
    static function getIndex(array $arrayToSearch, $key, $value) 
    { 
    $matches = self::filter($arrayToSearch, $key, $value); 
    if (!count($matches)) return false; 
    $indexes = array_keys($matches); 
    return $indexes[0]; 
    } 
} 

$array = array("1"=>array('username'=>'user1'), "3"=>array('username'=>'user2')); 

$matches = ArraySearch2d::filter($array, 'username', 'user2'); 
var_dump($matches); 

$indexs = array_keys($matches); 
var_dump($indexs); 

// Demonstrating quick answer: 
echo "Key for first 'username'=>'user1' element is: " 
    .ArraySearch2d::getIndex($array, 'username', 'user1')."\n"; 

Produce:

array(1) { 
    [3]=> 
    array(1) { 
    ["username"]=> 
    string(5) "user2" 
    } 
} 
array(1) { 
    [0]=> 
    int(3) 
} 
Key for first 'username'=>'user1' element is: 1 

Sin el uso de clases - esto produce el mismo resultado:

<?php 
$field="username"; 
$value = "user2"; 

function usernameMatch($element) 
{ 
    global $field, $value; 
    if (!is_array($element)) return false; 
    return $element[$field] == $value; 
} 

function getFirstIndex(array $array) 
{ 
    if (!count($array)) return false; 
    $indexes = array_keys($array); 
    return $indexes[0]; 
} 

$array = array("1"=>array('username'=>'user1'), "3"=>array('username'=>'user2')); 

$matches = array_filter($array, 'usernameMatch'); 
var_dump($matches); 

$indexs = array_keys($matches); 
var_dump($indexs); 


// Demonstrating quick answer - and why you should probably use the class- 
// you don't want to have to remember these "globals" all the time. 
$field = 'username'; 
$value = 'user1'; 

echo "Key for first 'username'=>'user1' element is: " 
    .getFirstIndex(array_filter($array, 'usernameMatch')); 
+0

seguramente el hecho de que necesita implementar una Clase o usar globales significa que estos no son buenos enfoques. Es bastante posible en un par de líneas de código, si solo usas un bucle. – nickf

+0

No pensé en el simple foreach hasta después de ver tu respuesta :) - Buen trabajo – gnarf

6

Esto sería muy simple

private function getArrayKey($haystack, $needle) 
{ 
    foreach($haystack as $key => $product) 
    { 
    if ($product['id'] === $needle) 
    return $key; 
    } 

    return false; 
} 
2

Si sabe que la la clave es username, simplemente use una matriz como el parámetro de búsqueda:

$username = 'user1'; 
$key = array_search(array('username' => $username), $array); 
Cuestiones relacionadas