Pete
Pete

Reputation: 465

Search the third level values of a 3d array for a given string and return the first level key

I'm trying to figure out a way to pass either the name of a state or a territory code to an array of sales representatives and have the script return that person's ID. Here is a sample:

$sales_people = [
    '2' => [
        'states' => ['NY', 'NJ', 'CT', 'MA', 'VT', 'ME'],
        'codes' => ['CA1', 'US7', 'UT9']
    ],
    '5' => [
        'states' => ['FL', 'GA', 'SC', 'NC', 'TN'],
        'codes' => ['VA4', 'VA8', 'VA3']
    ]
];

If $foo = 'VA4', how would I go about having the script return 5?
Similarly, if $foo = 'NJ', how would I have it return 2?

I was thinking of using in_array(), but it would appear as though that doesn't work on multidimensional arrays.

Upvotes: 1

Views: 52

Answers (2)

mickmackusa
mickmackusa

Reputation: 48070

Your haystack structure is not designed for performant searching, but you can use nested loops and an early break to search for a needle in the 3rd level data of the multidimensional array.

When performing a brute force search like this, it is important to break or return upon finding a match to avoid unnecessary iterations.

Code: (Demo)

function searchSubsets($sets, $needle): ?int
{
    foreach ($sets as $id => $haystacks) {
        foreach ($haystacks as $haystack) {
            if (in_array($needle, $haystack)) {
                return $id;
            }
        }
    }
    return null;
}
var_export(searchSubsets($sales_people, 'CT'));

If you were going to perform multiple searches on that data set, it would likely improve performance to convert it into a flat, associative lookup map for instant access.

Code: (Demo)

function populateLookup(array $sets): array
{
    $lookup = [];
    foreach ($sets as $id => $haystacks) {
        foreach ($haystacks as $haystack) {
            $lookup += array_fill_keys($haystack, $id);
        }
    }
    return $lookup;
}
$map = populateLookup($sales_people);
var_export($map);
echo "\n---\n";
var_export($map['CT'] ?? null);

After declaring such a lookup map, you could reference the array over and over without any more brute force searches.

Upvotes: 0

ComFreek
ComFreek

Reputation: 29444

If I understood you correctly, you want to search for the value in both keys (states and codes). If so, this code accomplishes it:

function sales_search($arr, $needle) {
  foreach ($arr as $id => $data) {
    if (in_array($needle, $data['states'])) {
      return $id;
    }

    if (in_array($needle, $data['codes'])) {
      return $id;
    }
  }
  return false;
}

Live example @ Ideone.com: http://ideone.com/wmfP2v

echo sales_search($sales_people, 'NJ');  // 2
echo sales_search($sales_people, 'VA4'); // 5

Upvotes: 2

Related Questions