简体   繁体   中英

How to get key based on value from a nested array?

This is an example of a nested array I'm working with. The "keys" representing locations are 720, and 715. The nested array values are services at said locations.

As you can tell from the values some are duplicated, and some are unique. I want to be able to take a single value or array such as 4512, 1110, 685 and then look up the relevant key.

So 4512 would return 720.

Done so far is: 1) Generated what I believe is a properly formatted array 2) Retrieved intersected values within nested arrays

Problem Summary: How to get the key from one of the values. I'm sorry but I tried array_search() without any luck.

Any help is appreciated, i'm still learning about arrays. Thanks.

array(
    2
)
    {
    [720] => array(
        4
    )
        {
        [0] => int(4512) [1] => int(1110) [2] => int(1803) [3] => int(669)
        }

    [715] => array(
        3
    )
        {
        [0] => int(1803) [1] => int(685) [2] => int(669)
        }
    }

Trying to search through that structure as-is is going to waste a lot of time since all of the entries need to be examined every time, but if you invert it it can be made much more efficient by leveraging PHP's array indexes for a direct lookup. eg:

$arr = [
  4512 => 720,
  1110 => 720,
  1803 => 715
];

echo $arr[4512]; // 720

Even creating a simple index like this in parallel to the main data structure will allow you to benefit from it.

As mentioned by Sammitch , if you have a large structure or plan on doing many queries, a linear search through the array inspecting each element on every search is an expensive and unnecessary operation. If you use the PHP function array_flip() , you can invert keys and values and index right into the array in constant time (meaning instantly regardless of how big your array is, if you haven't studied time complexity just yet).

One snag: array_flip() doesn't work when the input array's values aren't hashable types, as is the case here. So we write our own array_flip() that turns array values into keys.

I'm assuming any duplicate values should produce an array of the keys that map to them in the flipped array. Changing that policy to take the last or first key results in less code, if desired.

function flip($arr) {
    $flipped = [];

    foreach ($arr as $k => $v) {
        foreach ($v as $e) {
            if (!array_key_exists($e, $flipped)) {
                $flipped[$e] = $k;
            }
            else {
                if (is_array($flipped[$e])) {
                    $flipped[$e][] = $k;
                }
                else {
                    $flipped[$e] = [$flipped[$e], $k];
                }
            }
        }
    }

    return $flipped;
}

function find($needle, $haystack) {
    return array_key_exists($needle, $haystack) ? $haystack[$needle] : false;
}

$arr = [
  720 => [4512, 1110, 1803, 669],
  715 => [1803, 685, 669]
];
$flipped = flip($arr);

echo "the flipped array: \n";
print_r($flipped);

echo "\n\nsearching for 1803: \n";
print_r(find(1803, $flipped));
echo "\n\n";

echo "searching for 1: \n";
print_r(find(1, $flipped));
echo "\n\n";

echo "searching for 4512: \n";
print_r(find(4512, $flipped));
echo "\n\n";

Output:

the flipped array: 
Array
(
    [4512] => 720
    [1110] => 720
    [1803] => Array
        (
            [0] => 720
            [1] => 715
        )

    [669] => Array
        (
            [0] => 720
            [1] => 715
        )

    [685] => 715
)


searching for 1803: 
Array
(
    [0] => 720
    [1] => 715
)


searching for 1: 


searching for 4512: 
720

Try it here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM