How to locate a value in an array with a specific structure

Asked

Viewed 12,772 times

12

I need to locate the position of one array within another, in the following structure:

array{
  [0]=>{
    ["id"]=>"5744"
    ["fk"]=>"7"
    ["nome"]=>"Nivel 1"
    ["created"]=>"2014-04-30 16:54:14"
    ["modified"]=>NULL
    ["user_created"]=>NULL
    ["sadmin"]=>"N"
    ["color"]=>NULL
  }
  [1]=>{
    ["id"]=>"5745"
    ["fk"]=>"5744,7"
    ["nome"]=>"Nível 2"
    ["created"]=>"2014-04-30 16:56:21"
    ["modified"]=>NULL
    ["user_created"]=>NULL
    ["sadmin"]=>"N"
    ["color"]=>NULL
  }
  [2]=>{
    ["id"]=>"5746"
    ["fk"]=>"5745,5744,7"
    ["nome"]=>"Nível 3"
    ["created"]=>"2014-04-30 16:57:15"
    ["modified"]=>NULL
    ["user_created"]=>NULL
    ["sadmin"]=>"N"
    ["color"]=>NULL
  }
}

As an example: I own the value 5746 and I have to search through it, that is, I need everything that is at position 2 of the array.

I am editing to add important information that I have not mentioned:

the array is extremely large, and I will need to perform this search many times in this same array, so I need a solution without foreach, do a direct search without having to go through the entire array.

6 answers

7

I’m not experienced in php but I think this might help.

Assuming the input array is what you passed named as $valores:

$valores = array(
  0 => array(
    "id" =>"5744",
    "fk" =>"7",
    "nome" =>"Nivel 1",
    "created" =>"2014-04-30 16:54:14",
    "modified" =>NULL,
    "user_created" =>NULL,
    "sadmin" =>"N",
    "color" =>NULL),

  1 => array(
    "id"=>"5745",
    "fk"=>"5744,7",
    "nome"=>"Nível 2",
    "created"=>"2014-04-30 16:56:21",
    "modified"=>NULL,
    "user_created"=>NULL,
    "sadmin"=>"N",
    "color"=>NULL),

  2 => array(
    "id"=>"5746",
    "fk"=>"5745,5744,7",
    "nome"=>"Nível 3",
    "created"=>"2014-04-30 16:57:15",
    "modified"=>NULL,
    "user_created"=>NULL,
    "sadmin"=>"N",
    "color"=>NULL)
);

And to fetch the ID, you can use a simple for:

// Busca pelo elemento de ID 5746

foreach ($valores as &$valor) 
{
    if($valor["id"] == "5746")
    {
        // Array encontrado.
        print_r($valor);
    }
}

5


I am surprised that many answers, including voted answers, point out as a solution a coded code, that filter the matrix to a single occurrence, manually coded in a mere conditional.

Well... My suggestion is similar to that given by the friend @Cahe, but she much leaner and kills the problem with sniper precision and, breaking, still avails of more modern language features: Iterators.

It was not a solution created by me, hence the documentation in English, but I kept the credits of the author, including the link from where the snippet was removed. But unfortunately, either the same was removed from the manual, or deleted during the redesign of the site.

/**
 * Searches value inside a multidimensional array, returning its index
 *
 * Original function by "giulio provasi" (link below)
 *
 * @param mixed|array $haystack
 *   The haystack to search
 *
 * @param mixed $needle
 *   The needle we are looking for
 *
 * @param mixed|optional $index
 *   Allow to define a specific index where the data will be searched
 *
 * @return integer|string
 *   If given needle can be found in given haystack, its index will
 *   be returned. Otherwise, -1 will
 *
 * @see http://www.php.net/manual/en/function.array-search.php#97645
*/
function search( $haystack, $needle, $index = NULL ) {

    if( is_null( $haystack ) ) {
        return -1;
    }

    $arrayIterator = new \RecursiveArrayIterator( $haystack );

    $iterator = new \RecursiveIteratorIterator( $arrayIterator );

    while( $iterator -> valid() ) {

        if( ( ( isset( $index ) and ( $iterator -> key() == $index ) ) or
            ( ! isset( $index ) ) ) and ( $iterator -> current() == $needle ) ) {

            return $arrayIterator -> key();
        }

        $iterator -> next();
    }

    return -1;
}

To use, of course, just invoke the function by passing the array to be searched in the first argument and what is searched in the second.

var_dump( search( $valores, '5745,5744,7' ) ); // Saída int(2)

Optionally we have the third argument that allows you to restrict the search to a specific matrix index.

In the use example immediately above would be:

var_dump( search( $valores, '5745,5744,7', 'fk' ) );

It is not a performance gain because all logic resides in a single IF, but it is an alternative that deserves to be taken into account.

The function returns an integer that must be used to access the indexes of the matrix:

var_dump( $valores[ search( $valores, '5745,5744,7', 'fk' ) ] );

Note only that this didactic example takes into account a real and existing value. In an actual application where the searched value may not exist, a check must be made if the function returns -1, in view of the fact that, -1 is not a valid index for a matrix, even if it is, improperly, valid for PHP.

  • Perfect guy, it was exactly what I needed, without a loop to go through the whole array and extremely fast...

  • It loops, but by using Iterators, mainly a recursive, the task is much better performed than invoking the function itself again, again and again to each new array nested to the structure.

  • I got it. Thank God!

4

If you need to find the value 5746 independent of the key you can make:

foreach ($array as $key => $val){
  if (in_array("5746", $val)){
     $find = $val;
  }
}
print_r($find);

Or if you need to find the value 5746 for the key id, you can do;

foreach ($array as $key => $val){
  if ($val['id'] == 5746){
     $find = $val;
  }
}
print_r($find);

An option would also be to use a callback of function array_filter():

$array = array_filter($array, function($ar) { return ($ar['id'] == '5746'); });
  • I’ll try to use with the array_filter() and give feedback in sequence...

  • 1

    I used array_filter, I didn’t remember this function, thank you very much!

3

Even if the question is partially resolved, I will leave an example of an alternative implementation of the function array_search where you can "filter" a member of an array by certain values:

function array_match($needle, $haystack, $strict = TRUE)
{
    foreach($haystack as $key => $member) {
        if(is_array($member) === FALSE)
            continue; // procuramos somente em arrays
        $tomatch = count($needle); // quantos valores precisam ser iguais
        $matches = 0;
        foreach($needle as $nkey => $nvalue) {
            if(isset($member[$nkey]) === FALSE)
                break; // a sub-array não possui o valor
            if($strict === TRUE) {
                if($member[$nkey] === $nvalue)
                    $matches++;
                else
                    break; // o valor é diferente do que queremos
            } else {
                if($member[$nkey] == $nvalue)
                    $matches++;
                else
                    break; // o valor é diferente do que queremos
            }
        }
        if($tomatch == $matches)
            return $key; // encontramos
    }
    return NULL;
}

Example:

$needle = array(
    "id"=>"5746",
    "nome"=>"Nível 3",
    "sadmin"=>"N"
);
echo array_match($needle, $data); // "2"

The above code returns the index of $data which has the same elements and values as $needle, optionally you can tell if the comparison of the values should be strict (===) or not.

2

Starting with PHP 5.5.0, the new array_column() function can simplify the scripts we commonly use.

print_r( array_search( '5746', array_column( $array, 'id' ) ) );

Refer to the manual: http://php.net/array_column

1

    function busca($valores, $id){
        foreach($valores as $key => $value){
            if ($value['id'] == $id){
                return $value;
            }
        }
        return null;
    }

    var_dump(busca($valores, "5746"));

Browser other questions tagged

You are not signed in. Login or sign up in order to post.