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
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. But if it's too difficult on this side...)
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.
I'd just use a combination of foreach() using the below logic:
Check if both the arrays have same length.
Use foreach to walk through the array and fill in the final array.
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
Related
I have an array in PHP and I need to sort by a nested array inside of the array...
Here is my array:
Array
(
[0] => Array
(
[project_id] => 1
[earnest_money_due] => Array
(
[value] => 1000.00,
[currency] => 'USD'
)
)
[1] => Array
(
[project_id] => 2
[earnest_money_due] => Array
(
[value] => 200.00,
[currency] => 'USD'
)
)
[2] => Array
(
[project_id] => 3
[earnest_money_due] => Array
(
[value] => 900.00,
[currency] => 'USD'
)
)
Here's how I'm trying to sort it:
$records - this the array of records
$column - this is the the sortable column "earnest_money_due"
$columns = array_column($records, $column);
array_multisort($columns, SORT_ASC, $records);
I need to be able to sort by the [value] of the [earnest_money_due]. My code doesn't work because it's trying to sort an array, not a value.
Try this...
<?php
$array = [
[
'project_id' => 1,
'earnest_money_due' => [
'value' => 1000.00,
'currency' => 'USD',
],
],
[
'project_id' => 2,
'earnest_money_due' => [
'value' => 200.00,
'currency' => 'USD',
],
],
[
'project_id' => 3,
'earnest_money_due' => [
'value' => 900.00,
'currency' => 'USD',
],
],
];
array_multisort(
array_map(
static function ($element) {
return $element['earnest_money_due']['value'];
},
$array
),
SORT_ASC,
$array
);
var_dump($array);
If you remove the SORT_ASC, then your code works just fine. This is because PHP will sort your subarray as expected with it removed. It will compare from the start of the subarray. (Demo)
array_multisort(array_column($array, 'earnest_money_due'), $array);
If that seems too hacky, unreliable, or unintuitive, array_map() is fine. (Demo)
array_multisort(array_map(fn($row) => $row['earnest_money_due']['value'], $array), $array);
There is also nothing wrong with using usort(). (Demo)
usort($array, fn($a, $b) => $a['earnest_money_due']['value'] <=> $b['earnest_money_due']['value']);
Regardless of which array_multsort() technique you use, you don't need to explicitly use SORT_ASC because this is the default sorting order.
I am trying to merge arrays with the same keys with different values, like below.
Input:
$array1 = array('1933' => array(
'nid' => '492811',
'title' => 'NEW TITLE',
'field_link_single_url' => 'abc',
'field_link_single_title' => 'test'
));
$array2 = array('1933' => array(
'nid' => '492811',
'title' => 'NEW TITLE',
'field_link_single_url' => 'xyz',
'field_link_single_title' => 'abcd'
));
Expected output to be:
Array
(
[nid] => 492811
[title] => NEW TITLE
[field_link_single_url] => [
[0] => 'abc',
[1] => 'xyz'
]
[field_link_single_title] => [
[0] => 'test',
[1] => 'abcd'
]
)
I have tried array_merge and array_merge_recursive but it does not work as expected.
Output of array_merge_recursive($array1[1933], $array2[1933]) it is creating duplicates keys having same value
Array
(
[nid] => Array
(
[0] => 492811
[1] => 492811
)
[title] => Array
(
[0] => Hal Louchheim
[1] => Hal Louchheim
)
[field_link_single_url] => Array
(
[0] => abc
[1] => xyz
)
[field_link_single_title] => Array
(
[0] => test
[1] => abcd
)
)
I made some assumption. If these assumptions are not valid, you should add some additional checks:
Both $array1 and $array2 are really arrays
Both $array1 and $array2 have the exact same keys
The values inside $array1 and $array2 are primitive types, not complex objects (the === operator would not work to compare objects or arrays)
function mergeArrayValues($array1, $array2) {
$output = [];
foreach($array1 as $key => $value) {
$output[$key] = $array1[$key] === $array2[$key]
? $array1[$key]
: [ $array1[$key], $array2[$key] ]
}
return $output;
}
mergeArrayValues($array1[1933], $array2[1933])
This question already has answers here:
Merge arrays of associative arrays by shared column values [duplicate]
(3 answers)
Closed 5 months ago.
I have 2 array like follows:
$array1 = [
'0' => [
'no_invoice' => 'INV0001',
'product_code' => '1111111',
],
'1' => [
'no_invoice' => 'INV0001',
'product_code' => '1111112',
]
];
$array2 = [
'0' => [
'product_code' => '1111112',
'free_valie' => 839,
'count' => 1240
],
];
Is it possible to combine arrays above to be like this:
Array(
[0] => Array
(
'no_invoice' => 'INV0001',
'product_code' => '1111111',
)
[1] => Array
(
'no_invoice' => 'INV0001',
'product_code' => '1111112',
'free_valie' => 839,
'count' => 1240
)
)
So, if array have same product code, then it will join like the example above.
I have been tried with use array merge, array_merge($array1, $array2);
But the result is like this:
Array(
[0] => Array
(
'no_invoice' => 'INV0001',
'product_code' => '1111111',
)
[1] => Array
(
'no_invoice' => 'INV0001',
'product_code' => '1111112',
)
[2] => Array
(
'product_code' => '1111112',
'free_valie' => 839,
'count' => 1240
)
)
This code will do what you want. It loops over each value in $array1, using array_search to see if the entrie's product_code is also present in $array2 (by looking through the product_code column of $array2 extracted using array_column). If it is, the values are merged. Note that we use &$val in the foreach, causing the value to be passed by reference which allows it to be modified in the loop
foreach ($array1 as &$val) {
if (($k = array_search($val['product_code'], array_column($array2, 'product_code'))) !== false) {
$val = array_merge($val, $array2[$k]);
}
}
print_r($array1);
Output:
Array
(
[0] => Array
(
[no_invoice] => INV0001
[product_code] => 1111111
)
[1] => Array
(
[no_invoice] => INV0001
[product_code] => 1111112
[free_valie] => 839
[count] => 1240
)
)
Demo on 3v4l.org
Try below one.
$array1 = [
'0' => [
'no_invoice' => 'INV0001',
'product_code' => '1111111',
],
'1' => [
'no_invoice' => 'INV0001',
'product_code' => '1111112',
]
];
$array2 = [
'0' => [
'product_code' => '1111112',
'free_valie' => 839,
'count' => 1240
],
];
foreach ($array1 as $key => &$value) {
$key = array_search($value['product_code'], array_column($array2, 'product_code'));
if ($key !== false) {
$value = array_merge($value, $array2[$key]);
unset($array2[$key]);
$array2 = array_values($array2);
}
}
echo '<pre>';
print_r($array1);
exit;
I got this array. I want all the other 3 array come into this [0] => Array. Don't want unique value just want to merge all array flat in to [0] => Array.
Array
(
[0] => Array
(
[0] => Array
(
[Campaign] => xxx
[Phone] => 111
[State] => cd
)
)
[1] => Array
(
[0] => Array
(
[Campaign] => zxxxzx
[Phone] => 111111
[State] => zxxx
)
)
[2] => Array
(
[0] => Array
(
[Campaign] => aaaa
[Phone] => 111
[State] => Csd
)
)
[3] => Array
(
[0] => Array
(
[Campaign] => sasa
[Phone] => 111
[State] => asas
)
)
)
This is another example of how important the naming is. What you are working with is basically:
$recordsGroups = array(
// first group:
array(
// record 1:
array(
'key1' => 'val1',
'key2' => 'val2',
),
// record 2:
array(
'key1' => 'aaa',
'key2' => 'bbb',
),
),
// 2nd group:
array(
// record 3:
array(
'key1' => 'ccc',
'key2' => 'ddd',
),
),
);
And what you are probably trying to do is:
$records = array();
foreach ($recordsGroups as $group)
foreach ($group as $record)
$records[] = $record;
Which will give you:
$records = array(
// record 1:
array(
'key1' => 'val1',
'key2' => 'val2',
),
// record 2:
array(
'key1' => 'aaa',
'key2' => 'bbb',
),
// record 3:
array(
'key1' => 'ccc',
'key2' => 'ddd',
),
);
This should do nicely:
$array = call_user_func_array('array_merge', $array);
Or Argument unpacking via ... (splat operator):
$array = array_merge(...$array);
Because arrays can't have duplicate keys, the best that this multi-dim array can be condensed is down to an indexed array of associative arrays. array_column() will make quick work of this task.
Code: (Demo)
$array=[
[
['Campaign'=>'xxx','Phone'=>'111','State'=>'cd']
],
[
['Campaign'=>'zxxxzx','Phone'=>'111111','State'=>'zxxx']
],
[
['Campaign'=>'aaaa','Phone'=>'111','State'=>'Csd']
],
[
['Campaign'=>'sasa','Phone'=>'111','State'=>'asas']
]
];
var_export(array_column($array,0));
Output:
array (
0 =>
array (
'Campaign' => 'xxx',
'Phone' => '111',
'State' => 'cd',
),
1 =>
array (
'Campaign' => 'zxxxzx',
'Phone' => '111111',
'State' => 'zxxx',
),
2 =>
array (
'Campaign' => 'aaaa',
'Phone' => '111',
'State' => 'Csd',
),
3 =>
array (
'Campaign' => 'sasa',
'Phone' => '111',
'State' => 'asas',
),
)
I am trying to create filtered array 3 using array 1 and array 2.
ARRAY 1
Array (
[title] => value
[title2] => value2
[title3] => value3
)
ARRAY 2
Array (
[0] => Array ( [id] => 20 [title2] => value2 [otherColumn1] => otherValue1)
[1] => Array ( [id] => 21 [title4] => value4 [otherColumn3] => otherValue3)
)
Desired Result after applying the intersection method:
ARRAY 3
Array ( [title2] => value2 )
So far I am unable to achieve the result because array 1 and 2 have non-matching structures. I have tried different techniques but I am unable compare them due to structure differences.
if (!empty($data1['array2'][0])) {
foreach ($data1['array2'] as $key) {
// $filtered= array_intersect($array1,$key);
// print_r($key);
}
// $filtered= array_intersect($array1,$data1['array2']);// if i use $data1['array2'][0] it filters fine but just one row
// print_r($filtered);
}
Any help would be much appreciated. Thank you.
Given the arrays:
$arr = array('title' => 'value', 'title2' => 'value2', 'title3' => 'value3');
$arr2 = array (
0 => array ( 'id' => '20', 'title2' => 'value2', 'otherColumn1' => 'otherValue1'),
1 => array ( 'id' => '21', 'title4' => 'value4', 'otherColumn3' => 'otherValue3'));
You can get your filtered array with this:
$merged = call_user_func_array('array_merge', $arr2);
$filtered = array_intersect($arr, $merged);
If you want to intersect just according to the keys you can use this instead:
$filtered = array_intersect_key($arr, $merged);
you can remove structural difference in the following way
$arr1 = array (
0 => array('title' => 'value', 'title2' => 'value2', 'title3' => 'value3'));
$arr2 = array (
0 => array ( 'id' => '20', 'title2' => 'value2', 'otherColumn1' => 'otherValue1'),
1 => array ( 'id' => '21', 'title4' => 'value4', 'otherColumn3' => 'otherValue3'));