0

I have two arrays. One is a list of colors, the second is an associative array of key value pairs. My objective is to take the key value pairs from the associative array and make them a sub-array of each item in the colors array. Searching SO has gotten me various adjacent issues, but not the one I'm having specifically. Here are two example arrays, and then $final is what I want to achieve:

$colors = ['#eea845', '#64A0B4', '#003c50', '#FF5568', '#eee', '#5cb85c', '#5bc0de', '#f0ad4e', '#d9534f'];

$test = [
  'key1' => 'val1',
  'key2' => 'val2',
  'key3' => 'val3',
  'key4' => 'val4',
  'key5' => 'val5',
  'key6' => 'val6',
  'key7' => 'val7',
  'key8' => 'val8',
  'key9' => 'val9',
];

$final = [
   '#eea845' => [
      'name' => 'key1',
      'value' => 'val1',
   ],
   '#64A0B4' => [
      'name' => 'key2',
      'value' => 'val2',
   ],
   etc.....
]

I've been looking at array_walk, array_map, and trying to figure out how to combine for and foreach loops.

I looked at the answer given here (Append one array values as key value pair to another array php), but I'm not sure how to use it on an already existing array and be able to get the index of each.

For example, that solution uses:

array_walk($array1, function(&$v, $k) use($array2) {
    $v['date'] = $array2[$k];
});

but I need to have the values from $array2 be added to already existing items in $array1, and while I tried doing function($i, $v, $k) with $i being the index inside $array1, that didn't work, $i being undefined.

I'm stumped and not sure where to look next. How would you synchronously iterate the two arrays to build a structure like this:

return $colors[$i] => 
  [
   'name' => $test[$key], 
   'value' => $test[$name] 
  ]

For context, I am using this to get values to input into a Twig template, and this looks like the best way to do it for that half of the problem.

1
  • array_map then array_combine Commented Nov 10, 2021 at 22:14

3 Answers 3

1

There are several ways to do it. One way is to use foreach on the associative array, so you get key and value in separate variables, and to use next() to get the corresponding value from the first (indexed) array:

foreach ($test as $key => $value) {
    $final[current($colors)] = ["name" => $key, "value" => $value];
    next($colors);
}

In the rare event you had already used next() on $colors, you'll have to call reset($colors) before starting this loop.

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

1 Comment

Or with array_shift() if mutating/destroying the $colors array is tolerable. 3v4l.org/G96iD Or without destroying the $colors while maintaining a counter. 3v4l.org/eMmUf
1

I'd just use a combination of foreach() using the below logic:

  1. Check if both the arrays have same length.
  2. Use foreach to walk through the array and fill in the final array.
  3. I am not good in this point, but I use a $count to keep track of the index. You can use cursors like next($colors) and current($colors), but I am not sure.
<?php
$colors = [
    '#eea845', '#64A0B4', '#003c50', '#FF5568', '#eee', '#5cb85c', '#5bc0de', '#f0ad4e', '#d9534f'
];

$test = [
  'key1' => 'val1',
  'key2' => 'val2',
  'key3' => 'val3',
  'key4' => 'val4',
  'key5' => 'val5',
  'key6' => 'val6',
  'key7' => 'val7',
  'key8' => 'val8',
  'key9' => 'val9',
];

if (count($colors) == count($test)) {
    $count = 0;
    $finalOne = array();
    foreach ($test as $key => $value) {
        $finalOne[$colors[$count]] = [
            "name" => $key,
            "value" => $value
        ];
        $count++;
    }
    print_r($finalOne);
} else {
    echo "Arrays are of not same length.";
}

Output

Array
(
    [#eea845] => Array
        (
            [name] => key1
            [value] => val1
        )

    [#64A0B4] => Array
        (
            [name] => key2
            [value] => val2
        )

    [#003c50] => Array
        (
            [name] => key3
            [value] => val3
        )

    [#FF5568] => Array
        (
            [name] => key4
            [value] => val4
        )

    [#eee] => Array
        (
            [name] => key5
            [value] => val5
        )

    [#5cb85c] => Array
        (
            [name] => key6
            [value] => val6
        )

    [#5bc0de] => Array
        (
            [name] => key7
            [value] => val7
        )

    [#f0ad4e] => Array
        (
            [name] => key8
            [value] => val8
        )

    [#d9534f] => Array
        (
            [name] => key9
            [value] => val9
        )

)

Working Demo: http://sandbox.onlinephpfunctions.com/code/73fb63fab8ccbdb6f73c795572ae51a0d98acdb4

2 Comments

Please use 3v4l.org as your demo'ing sandbox. The UX on mobile devices is abysmal on sandbox.onlinephpfunctions.com
@mickmackusa This is the first time I am hearing about 3v4l.org. Thank you so much. ❤️
0

As long as you aren't dealing with hundreds of thousands of array elements, performance is probably not going to be a concern, so don't instantly discount approaches which have higher time complexity.

A functional approach with no array pointer management: Demo

var_export(
    array_combine(
        $colors,
        array_map(
            fn($name, $value) => get_defined_vars(),
            array_keys($test),
            $test
        )
    )
);

A way to make @trincot's script less verbose is to call compact to build associative elements from variable names. Demo

$result = [];
foreach ($test as $name => $value) {
    $result[current($colors)] = compact('name', 'value');
    next($colors);
}
var_export($result);

All of my attempts to implement a "generator" script or PHP's native "Iterator" class methods produce an ugly/noisy block of code, so I'll not mention them.

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.