roflwaffle
roflwaffle

Reputation: 30666

Get index of row with qualifying value from a 2d array

I have this array in PHP:

array(
    [0] => array( 'username' => 'user1' )
    [1] => array( 'username' => 'user2' )
)

If I have the 'username' string how can I get the index value as a number?

Example, if I have 'user1' how can I get 0?

Upvotes: 29

Views: 79483

Answers (5)

Shaolin
Shaolin

Reputation: 2551

Loop through the array and compare the sought value against the specific associative element in each row until a match is found.

As soon as a match is found return the row's index to break the loop -- this will provide best efficiency.

If there are no rows that contain the qualifying data, then false will be returned.

private function getRowKeyByUsername($haystack, $needle)
{
    foreach ($haystack as $key => $row) {
        if ($row['username'] === $needle) {
            return $key;
        }
    }
    return false;
}

Upvotes: 7

AbraCadaver
AbraCadaver

Reputation: 79004

If you know that the key is username, just use an array as the search parameter:

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

Upvotes: 3

nickf
nickf

Reputation: 546303

If you have a 2D array, like in your example, you'll need to customise things a little:

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

If you wanted to search in just one particular field, you could alter the function to something like this:

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

Upvotes: 25

gnarf
gnarf

Reputation: 106392

Perhaps using array_filter and array_keys together will help.

Class Based Approach.

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

Produces:

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

Without using classes - this produces the same result:

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

Upvotes: 2

Dan Walker
Dan Walker

Reputation: 7163

Take a look at array_search.

From the PHP help file:

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

Upvotes: 26

Related Questions