1

I have this array:

$params = [
    ['name'  => 'xxx', 'value' => 'yyy'],
    ['name'  => 'uuu', 'value' => 'vvv']
];

and I want to achieve this:

$params = [
    ['xxx' => 'yyy'],
    ['uuu' => 'vvv']
];

I can do it this way:

foreach ($params as &$param) {
    $param[$param['name']] = $param['value'];
    unset($param['name']);
    unset($param['value']);
    unset($param);
}

But I am wondering if this could be done on more elegant way?

2
  • 3
    codereview.stackexchange.com may be more appropriate -- elegance is extremely subjective Commented May 24, 2018 at 12:23
  • If you're looking for a built in way to accomplish this, there isn't one. You're code is short, accomplishes the task and is readable. I would use it. Commented May 24, 2018 at 12:24

7 Answers 7

6

This calls for an array mapping of values:

$params = array_map(function ($i) { return [$i['name'] => $i['value']]; }, $params);
Sign up to request clarification or add additional context in comments.

4 Comments

That's in the eye of the beholder. A mapping is a defined action, and all you need to know is that 1) this is a mapping, 2) what the callback returns. Then it's very precise and readable. Too bad PHP's verbose syntax makes it somewhat ungainly.
E.g. in Javascript this would be params = params.map(i => ({ [i.name]: i.value })). It hardly gets any more concise than this, and the concept translates to most other languages.
Yes, I was making the point that OP was asking for elegance and NOT for the smallest possible codeblock. I believe it to be a poor question and this is only a subjectively beautiful answer :-p
Well, I consider references and superfluous variables inelegant. IMO this is about as elegant as it gets in PHP.
1

You can use array_map to reiterate the array.

$params = [
  [
    'name'  => "xxx",
    'value' => "yyy"
  ],
  [
    'name'  => "uuu",
    'value' => "vvv"
  ]
];

$params = array_map(function($o){
    return [ $o['name'] => $o['value'] ];
}, $params);


echo "<pre>";
print_r( $params );
echo "</pre>";

This will result to:

Array
(
    [0] => Array
        (
            [xxx] => yyy
        )

    [1] => Array
        (
            [uuu] => vvv
        )

)

Doc: array_map()

2 Comments

Just curious, what is the difference with the answer of @deceze?
@Thefourthbird I didn't realize that someone already answered this approach. Until just now. Haha
0

This is a bit shorter. By not using foreach you can directly replace the elements.

for ($i = 0; $i < count ($params); $i++)
    $params[$i] = array ($params[$i]['name'] => $params[$i]['value']);

Comments

0

To make your current code a little bit more elegant, you could pass multiple arguments to unset

foreach ($params as &$param) {
    $param[$param['name']] = $param['value'];
    unset($param['name'], $param['value'], $param);
}

3 Comments

@Martin You don't have to do it to be able to use the new key, but as the OP wanst to remove the old keys and values in the example you could use it.
Yes that's a fair point. I had missed that; I was looking at it purely as a case of tidying up the foreach system.
No it's not, if you don't unset the values you will have three items in each subarray. But if you build a new array, then yes.
0

Try this :

foreach ($params as $key => $sub_array) {

    // unset original array data
    unset($params[$key]);

    // construct the new values
    $params[$key][$sub_array['name']] = $sub_array['value'];
}

EDIT:

Another approach more elegant is the following :

foreach($params as $k=>$s){
    $params[$k]=array($s['name']=>$s['value']);
}

2 Comments

why, what does this do? explain your answer
It simply put the name value in the key of parent array as you want. And unset the current name and value values. That's what you want. You only forgot to use $key in foreach to help you construct the array.
0

All of the following snippets will produce the same desired result from the provided input array. Demo

Make a new array with a body-less loop.

$result = [];
foreach ($params as ['name' => $k, 'value' => $result[][$k]]);
var_export($result);

Make a new array using iterated chunk&combining.

var_export(
    array_map(
        fn($row) => array_combine(...array_chunk($row, 1)),
        $params
    )
);

Make a new array using iterated hardcoded declarations.

var_export(
    array_map(
        fn($row) => [$row['name'] => $row['value']],
        $params
    )
);

Make a new array by reducing the columns to a flat associative array, then re-expand to a 2d array.

var_export(
    array_chunk(
        array_column($params, 'value', 'name'),
        1,
        true
    )
);

Modify the original array by reference without using first level keys.

foreach ($params as &$row) {
    $row = [$row['name'] => $row['value']];
}
var_export($params);

Comments

-3

Please try this:

foreach ($params as $k => $v)
{
    $nary[$v[name]] = $v[value];
}

$params = $nary;

3 Comments

this won't work without quotes around name and value. Also OP already says they can do it this way and want something more elegant
@ThisGuy Depressingly "$v[name]" will work just fine and $v[value] will in fact work for the time being (albeit generating a notice)…
@deceze ah I edited question for easier reading and forgot no one else can see it XD agreed that it is depressing it still works how it is

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.