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

12

I need to find the position of an array inside 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 have the value 5746 and I have to search through it, that is, I need everything in position 2 of the array.

I'm editing to add some important information that I did not mention:

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

    
asked by anonymous 30.04.2014 / 22:58

6 answers

4

I'm amazed many answers, including voted answers, point to an embedded code as a solution, filtering the array to a single occurrence, manually encoded in a conditional-only.

Well ... My suggestion is similar to that given by the @Cahe friend, but it's much leaner and kills the problem with sniper precision, and, by the way, still uses the more modern features of the language: Iterators. p>

It was not a solution I created, hence the documentation in English, but I kept the author's credits, including the link from where the snippet was removed. But unfortunately, or the same has been removed from the manual, or deleted during the site's repagination.

/**
 * 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, it is enough to invoke the function by passing the array to be fetched 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 index of the array.

In the example use 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 should be used to access the array's indexes:

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

Just notice that this didactic example takes into account a real and existing value. In a real application where the value you are looking for may not exist, a check should be made if the function returns -1 , since -1 is obviously not a valid index for an array, even if it is unduly valid for PHP.

    
13.05.2014 / 21:21
7

I'm not experienced at php but I think this might help.

Assuming that the input array is what you passed 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 get 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);
    }
}
    
30.04.2014 / 23:11
4

If you need to find the value 5746 regardless of the key you can do:

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

One option would also be to use a callback fault function array_filter () :

$array = array_filter($array, function($ar) { return ($ar['id'] == '5746'); });
    
30.04.2014 / 23:25
3

Even though the question is partially resolved, I will leave an example of an alternative implementation of the array_search function 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 that has the same elements and values of $needle , optionally you can tell whether the comparison of values should be strict ( === ) or not.

    
01.05.2014 / 00:20
2

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

See the manual: link

    
13.05.2014 / 20:39
1
    function busca($valores, $id){
        foreach($valores as $key => $value){
            if ($value['id'] == $id){
                return $value;
            }
        }
        return null;
    }

    var_dump(busca($valores, "5746"));
    
30.04.2014 / 23:30