2

This should be an easy one liner, but I can't quite get it:

I have an array like this:

$a = ["z", "x", "y"];

and an array like this:

$b = ["x"=>"a", "y"=>"b", "z"=>"c"];

what is a php oneliner to get:

$c = ["c", "a", "b"];

I want to use each element of a to index into b and return an array of the results I've been looking at array_map but couldn't figure out how to bind b to the callback function.

8
  • 1
    If there is any, it is on this list. Commented Dec 17, 2013 at 15:24
  • @Mołot, thanks this is the list I was looking at. It seems like array_map is the "correct" choice here, but I don't know how to bind $b as a parameter to the callback? Does anyone know how to do this? Commented Dec 17, 2013 at 15:38
  • 1
    You're missing return in your function. And use($b) does the binding Commented Dec 17, 2013 at 15:43
  • @onetrickpony, thanks I found that in the manual. This is the part I was missing. If you update your answer, or post another, with the array_map version, I will accept it. I am testing this now. Commented Dec 17, 2013 at 15:56
  • 1
    Just use the one you find easier to understand Commented Dec 17, 2013 at 16:07

4 Answers 4

2
$c = array_merge(array_intersect_key(array_flip($a), $b), $b);
$c = array_values($c);

Not really a one-liner, but close :P

Sign up to request clarification or add additional context in comments.

2 Comments

It can be written as a one-liner though.
array_merge(..., $b) adds everything from $b, so this solution is probably incorrect. array_values(array_intersect_key($b, array_flip($a))) is better but order of resulting elements is different.
2
$c = array();
foreach ($a as $key => $value)
{
    if (isset($b[$value]))
    {
       $c[] = $b[$value];
    }
}

3 Comments

@TFinnis, I was going down this road but figured there was a more "functional" way to do this. I will probably choose onetrickpony as the answer, but I gave you a +1 for the working solution.
This code is wrong. I suggested this as an edit, but it seems to have been rejected. $a is not an associative array, so $key will be set to the positional indices: [0, 1, 2]. To correct the code, lose ` => $value` in the foreach line.
@joeshmo, after looking again, you are correct. My intent is that $a is not used as an associative array. I think your fix is right for my situation.
1

Here is the solution I ended up with with help from @onetrickpony:

$a = array("z", "x", "y");
$b = array("x"=>"a", "y"=>"b", "z"=>"c");

$c = array_map(function($key) use ($b){ return $b[$key]; }, $a);

The key to this is the 'use' keyword to bind to the associative array to the closure. Pretty simple once you know what you are looking for :-)

Comments

1

With modern PHP, you can use arrow function syntax to access the second array without use(). As you iterate all of the values in the first array, check the mapping/second array for a matching key. If a match is found, use that; otherwise use the null coalescing operator to fallback to the original value.

Code: (Demo)

var_export(
    array_map(
        fn($v) => $b[$v] ?? $v,
        $a
    )
);

With the asker's original arrays, all elements are mapped, so the null coalescing is not necessary -- this is just a way to cover similar questions with missing keys in the lookup array.

If the lookup array might contain null values, then you'll need to use key_exists() like this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.