Merge array with common value - php

I have two arrays namely arr and arr2.
var arr=[{"month":"January","url":1},{"month":"February","url":102},{"month":"March","url":192}];
var arr2=[{"month":"January","ip":12},{"month":"June","ip":10}];
Is it possible to get array below shown from above two arrays?
result=[{"month":"January","url":1,"ip":12},{"month":"February","url":102},{"month":"March","url":192},{"month":"June","ip":10}];
If i use array_merge then i get answer as
result=[{"month":"January","url":1},{"month":"February","url":102},{"month":"March","url":192},{"month":"January","ip":12},{"month":"June","ip":10}];

You must decode JSON to arrays, manually merge them and again encode it to JSON :)
<?php
$arr = json_decode('[{"month":"January","url":1},{"month":"February","url":102},{"month":"March","url":192}]', true);
$arr2 = json_decode('[{"month":"January","ip":12},{"month":"June","ip":10}]', true);
$result = [];
foreach ($arr as &$item) {
if (empty($arr2))
break;
foreach ($arr2 as $key => $item2) {
if ($item['month'] === $item2['month']) {
$item = array_merge($item, $item2);
unset($arr2[$key]);
continue;
}
}
}
if (!empty($arr2))
$arr = array_merge($arr, $arr2);
echo json_encode($arr);

The first function that comes to mind is array_merge_recursive(), but even if you assign temporary associative keys to the subarrays, you end up with multiple January values in a new deep subarray.
But do not despair, there is another recursive function that can do this job. array_replace_recursive() will successfully merge these multidimensional arrays so long as temporary associative keys are assigned first.
Here is a one-liner that doesn't use foreach() loops or if statements:
Code: (Demo)
$arr=json_decode('[{"month":"January","url":1},{"month":"February","url":102},{"month":"March","url":192}]',true);
$arr2=json_decode('[{"month":"January","ip":12},{"month":"June","ip":10}]',true);
echo json_encode(array_values(array_replace_recursive(array_column($arr,NULL,'month'),array_column($arr2,NULL,'month'))));
Output:
[{"month":"January","url":1,"ip":12},{"month":"February","url":102},{"month":"March","url":192},{"month":"June","ip":10}]
The breakdown:
echo json_encode( // convert back to json
array_values( // remove the temp keys (reindex)
array_replace_recursive( // effectively merge/replace elements associatively
array_column($arr,NULL,'month'), // use month as temp keys for each subarray
array_column($arr2,NULL,'month') // use month as temp keys for each subarray
)
)
);

You should write your own function to do that
$res = [];
foreach ($arr as $item) {
$res[$item['month']] = $item;
}
foreach ($arr2 as $item) {
$res[$item['month']] = isset($res[$item['month']]) ? array_merge($res[$item['month']], $item) : $item;
}
var_dump($res);

Related

Replace array value with more than one values

I have an array like this,
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
I want to find any value with an ">" and replace it with a range().
The result I want is,
array(
1,2,3,4,5,6,7,8,9,10,11,12, '13.1', '13.2', 14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
);
My understanding:
if any element of $array has '>' in it,
$separate = explode(">", $that_element);
$range_array = range($separate[0], $separate[1]); //makes an array of 4 to 12.
Now somehow replace '4>12' of with $range_array and get a result like above example.
May be I can find which element has '>' in it using foreach() and rebuild $array again using array_push() and multi level foreach. Looking for a more elegant solution.
You can even do it in a one-liner like this:
$array = array(1,2,3,'4>12','13.1','13.2','14>30');
print_r(array_reduce(
$array,
function($a,$c){return array_merge($a,#range(...array_slice(explode(">","$c>$c"),0,2)));},
[]
));
I avoid any if clause by using range() on the array_slice() array I get from exploding "$c>$c" (this will always at least give me a two-element array).
You can find a little demo here: https://rextester.com/DXPTD44420
Edit:
OK, if the array can also contain non-numeric values the strategy needs to be modified: Now I will check for the existence of the separator sign > and will then either merge some cells created by a range() call or simply put the non-numeric element into an array and merge that with the original array:
$array = array(1,2,3,'4>12','13.1','64+2','14>30');
print_r(array_reduce(
$array,
function($a,$c){return array_merge($a,strpos($c,'>')>0?range(...explode(">",$c)):[$c]);},
[]
));
See the updated demo here: https://rextester.com/BWBYF59990
It's easy to create an empty array and fill it while loop a source
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
$res = [];
foreach($array as $x) {
$separate = explode(">", $x);
if(count($separate) !== 2) {
// No char '<' in the string or more than 1
$res[] = $x;
}
else {
$res = array_merge($res, range($separate[0], $separate[1]));
}
}
print_r($res);
range function will help you with this:
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
$newArray = [];
foreach ($array as $item) {
if (strpos($item, '>') !== false) {
$newArray = array_merge($newArray, range(...explode('>', $item)));
} else {
$newArray[] = $item;
}
}
print_r($newArray);

How to create an array of arrays from another array filtering it by a specific key of the subarrays?

I have following array of arrays:
$array = [
[A,a,1,i],
[B,b,2,ii],
[C,c,3,iii],
[D,d,4,iv],
[E,e,5,v]
];
From this one, I would like to create another array where the values are extract only if the value of third key of each subarray is, for example, greater than 3.
I thought in something like that:
if $array['2'] > 3){
$new_array[] = [$array['0'],$array['2'],$array['3']];
}
So in the end we would have following new array (note that first keys of the subarrays were eliminate in the new array):
$new_array = [
[D,4,iv],
[E,5,v]
];
In general, I think it should be made with foreach, but on account of my descripted problem I have no idea how I could do this. Here is what I've tried:
foreach($array as $value){
foreach($value as $k => $v){
if($k['2'] > 3){
$new_array[] = [$v['0'], $v['2'], $v['3']];
}
}
}
But probably there's a native function of PHP that can handle it, isn't there?
Many thanks for your help!!!
Suggest you to use array_map() & array_filter(). Example:
$array = [
['A','a',1,'i'],
['B','b',2,'ii'],
['C','c',3,'iii'],
['D','d',4,'iv'],
['E','e',5,'v']
];
$newArr = array_filter(array_map(function($v){
if($v[2] > 3) return [$v[0], $v[2], $v[3]];
}, $array));
print '<pre>';
print_r($newArr);
print '</pre>';
Reference:
array_map()
array_filter()
In the first foreach, $v is the array you want to test and copy.
You want to test $v[2] and check if it match your condition.
$new_array = [];
foreach($array as $v) {
if($v[2] > 3) {
$new_array[] = [$v[0], $v[2], $v[3]];
}
}

How to get the keys in a PHP Array by position?

I have an array where I store key-value pair only when the value is not null. I'd like to know how to retrieve keys in the array?
<?php
$pArray = Array();
if(!is_null($params['Name']))
$pArray["Name"] = $params['Name'];
if(!is_null($params['Age']))
$pArray["Age"] = $params['Age'];
if(!is_null($params['Salary']))
$pArray["Salary"] = $params['Salary'];
if(count($pArray) > 0)
{
//Loop through the array and get the key on by one ...
}
?>
Thanks for helping
PHP's foreach loop has operators that allow you to loop over Key/Value pairs. Very handy:
foreach ($pArray as $key => $value)
{
print $key
}
//if you wanted to just pick the first key i would do this:
foreach ($pArray as $key => $value)
{
print $key;
break;
}
An alternative to this approach is to call reset() and then key():
reset($pArray);
$first_key = key($pArray);
It's essentially the same as what is happening in the foreach(), but according to this answer there is a little less overhead.
Why not just do:
foreach($pArray as $k=>$v){
echo $k . ' - ' . $v . '<br>';
}
And you will be able to see the keys and their values at that point
array_keys function will return all the keys of an array.
To obtain the array keys:
$keys = array_keys($pArray);
To obtain the 1st key:
$key = $keys[0];
Reference : array_keys()

Display array_key from PHP array?

Here I am Having an Issue:
I have two arrays like the following:
$array1 = array('1','2','1','3','1');
$array2 = array('1','2','3'); // Unique $array1 values
with array2 values i need all keys of an array1
Expected Output Is:
1 => 0,2,4
2 => 1
3 => 3
here it indicates array2 value =>array1 keys
Just use a loop:
$result = array();
foreach ($array1 as $index => $value) {
$result[$value][] = $index;
}
If you pass array_keys a 2nd parameter, it'll give you all the keys with that value.
So, just loop through $array2 and get the keys from $array1.
$result = array();
foreach($array2 as $val){
$result[$val] = array_keys($array1, $val);
}
The following code will do the job. It will create a result array in which the attribute val will contain the value that is searched in array and keys attribute will be an array that contains the found keys. Based on your values following is an example:
$array1 =array('1','2','1','3','1');
$array2 =array('1','2','3');
$results = array();
foreach ($array2 as $key2=>$val2) {
$result = array();
foreach ($array1 as $key1=>$val1 ) {
if ($val2 == $val1) {
array_push($result,$key1);
}
}
array_push($results,array("val"=>$val2,keys=>$result ));
}
echo json_encode($results);
The result will be:
[{"val":"1","keys":[0,2,4]},
{"val":"2","keys":[1]},
{"val":"3","keys":[3]}]

Foreaching an array and matching?

How would I iterate through an array (300+ items, imported via simplexml) and pull out every item that has a certain $x->channel->item->title and put that into a different array?
I can't make heads or tails of the haystack needle thing or how to push arrays
Say I have an array (needle) like: array("3332","3300","3493","8380") and I want to match if any of those appear through the big array (haystack). How do I do this?
You have to iterate over your big array, and check for the value of $x->channel->item->title. If it meets your criteria, push it into the new array:
$theArray; // Your 300+ array
$lookFor = array('firstthing', 'second thing', 'third thing');
$newArray = array();
foreach($theArray as $x) {
if ( in_array($x->channel->item->title, $lookFor) ) {
array_push($newArray, $x);
}
}
foreach($yourArray as $key => $value)
{
//do your things with $key and/or $value
}
Modifying from Joseph's loop, you can do:
$theArray; // Your 300+ array
$newArray = array();
$matchArray = array("3332","3300","3493","8380");
foreach($theArray as $x) {
if (in_array($x->channel->item->title, $matchArray)) {
array_push($newArray, $x);
}
}
Check out in_array() at http://php.net/manual/en/function.in-array.php

Categories