0

The Microsoft QnAMaker API is returning a JSON key/value array (Metadata) in the following format:

$array = [[
    "name" => "someName1",
    "value" => "someValue1",
],
[
    "name" => "someName2",
    "value" => "someValue2",
],
 ..etc..
];

How do i transform it to be in the following more usable format:

$array = [
    "someName1" => "someValue1",
    "someName2" => "someValue2",
    ..etc..
];

I know I can do it using a loop... Is there a way to leverage on built in functions?

If a loop is the only way, how would you write it and why (performance/readibility/etc.)?

7
  • Could you not simply store $array[0][0] in a temp variable and then remove the second index --> $array[0][0] -- then set $array[0] ? Commented Oct 23, 2018 at 17:47
  • @Zak - not sure what you mean... Commented Oct 23, 2018 at 17:54
  • Any reason you don't want to just use a loop? It's only like 3 lines Commented Oct 23, 2018 at 17:56
  • @Leo after looking at it more closely, what you are asking is a little more complicated as far as restructuring your array -- You are trying to use key values as key identifiers -- This is going to require a loop .. There's just no other way around it. Commented Oct 23, 2018 at 17:56
  • 1
    Sounds like what you're thinking of is flatmap. PHP doesn't have that built-in. Other folks have created their own: gist.github.com/davidrjonas/8f820ab0c75534b45189eba1d1fbeb23 ... which is effectively what has been posted already. Commented Oct 23, 2018 at 18:08

7 Answers 7

2

If it looks JSONish, array_column helps. Simply:

<?php
var_export(array_column($array, 'value', 'name'));

Output:

array (
    'someName1' => 'someValue1',
    'someName2' => 'someValue2',
)
Sign up to request clarification or add additional context in comments.

2 Comments

Nice solution, I didn't know you could pass 3 variables to array_column() like that.
@GrumpyCrouton I did, and yet it took more than a while to come back to me. You can get a long way with some simple constructs such as a foreach. I'm always going back to the manual for array function lookups (blushes)..
2

This uses a combination of array_map() to re-map each element and then array_merge() to flatten the results...

print_r(array_merge(...array_map(function($data) 
                         { return [ $data['name'] => $data['value']]; }
                       , $array)));

It's not very elegant and would be interesting to see other ideas around this.

Which gives...

Array
(
    [someName1] => someValue1
    [someName2] => someValue2
)

8 Comments

This would produce Array ( [someName1] => someName2 [someValue1] => someValue2 )
@Zak, thanks - I've altered the code and actually checked the results this time.
...array_map - sorry i'm new to php... what does ... in front of function do?
@Leo -- It's called a "splat" operator lornajane.net/posts/2014/php-5-6-and-the-splat-operator
Anyone else maintaining your code will thank you for going with a loop :)
|
2

There isn't really a way besides a loop, so just loop through the array, and create a new array the way you need it.

$new_array = [];
foreach($array as $row) {
    $new_array[$row['name']] = $row['value'];
}

print_r($new_array);

There may be a few functions you can tie together to do what you want, but in general, the loop would probably be more readable and easier in overall.

1 Comment

It's a much simpler way of doing it and more maintainable IMHO.
2

As my previous answer was a dupe of GrumpyCroutons, I thought I'd rewrite with many array functions for good measure. (But don't use this, just do a simple foreach).

<?php
array_walk($array, function($v) use (&$result) {
    $result[array_shift($v)] = array_values($v)[0];
});

var_export($result);

Output:

array (
  'someName1' => 'someValue1',
  'someName2' => 'someValue2',
)

3 Comments

@GrumpyCrouton et al, hold your horses, I hadn't seen any answers when posting.
This is a good and valid answer - but I would note that array_walk() may not necessarily be faster than foreach() (Also, since this is a good and valid answer, I gave you an upvote to balance out that downvote you got when your answer was a duplicate)
@GrumpyCrouton I would say valid, but not good, rather ugly. I do note that a simple foreach would be preferable and dare I say, the pythonic way to do this.
1

This works:

$res = [];
array_walk($array, function(&$e) use(&$res) {
    $res[$e['name']] = $e['value'];
    unset($e); // this line adds side effects and it could be deleted
});
var_dump($res);

Output:

array(2) { 
   ["someName1"]=> string(10) "someValue1" 
   ["someName2"]=> string(10) "someValue2" 
} 

Comments

1

You can simply use array_reduce:

<?php
$output = array_reduce($array, function($a, $b) {
    $a[$b['name']] = $b['value'];

    return $a;
});

var_export($output);

Output:

array (
    'someName1' => 'someValue1',
    'someName2' => 'someValue2',
)

Comments

1

While getting a shift on (a non-foreach):

<?php
$c = $array;
while($d = array_shift($c))
    $e[array_shift($d)] = array_shift($d);

var_export($e);

Output:

array (
    'someName1' => 'someValue1',
    'someName2' => 'someValue2',
)

Although it suggests in the comments in the manual that shifting is more expensive than popping. You could replace the initial assignment to $c above with an array_reverse and the while-shift with a while-pop.

However, either approach is probably lousy compared to a foreach, but here for who knows whos amusement.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.