Codeigniter - merge multiple associative array with condition - php

I need to merge multiple arrays into one where a specific key & its value are same. Here is the Sample_Array1
array(n) {
[0]=> array {
["a"]=> "m1"
["b"]=> "x2"
}
[1]=> array {
["a"]=> "n1"
["b"]=> "y2"
} ....
Sample_Array2 with one common key & other different ones.
array(n) {
[0]=> array {
["b"]=> "x2"
["c"]=> "p1"
}
[1]=> array {
["b"]=> "x2"
["d"]=> "q1"
}
[2]=> array {
["b"]=> "y2"
["e"]=> "r1"
} ....
Need to merge / append Sample_Array2 to Sample_Array1 where key-"b" & its value are same. The expected output:
array(n) {
[0]=>
array(2) {
["a"]=> "m1"
["b"]=> "x2"
["c"]=> "p1"
["d"]=> "q1"
}
[1]=>
array(2) {
["a"]=> "n1"
["b"]=> "y2"
["e"]=> "r1"
} ....
I have tried so many similar questions but couldn't find the exact result.
PHP merge arrays with a condition The answer given on this link is not solving the purpose, its making different array for each new key, while I need to append the new keys in one array.

This should work, assuming you have the "b" index in all sub arrays.
$array1 = array();
$array1[] = array("a" => "m1", "b" => "x2", "c" => null);
$array1[] = array("a" => "n1", "b" => "y2");
$array2 = array();
$array2[] = array("b" => "x2", "c" => "p1");
$array2[] = array("a" => null, "b" => "x2", "d" => "q1");
$array2[] = array("b" => "y2", "e" => "r1");
function merge_on_key($array1, $array2, $key) {
$result_array = array();
foreach($array1 as $key1 => $sub_array1) {
$merged_array = array();
$sub_array1 = array_filter($sub_array1);
foreach($array2 as $key2 => $sub_array2) {
$sub_array2 = array_filter($sub_array2);
if($sub_array1[$key] == $sub_array2[$key]) {
$merged_array = array_merge($sub_array1, $sub_array2, $merged_array);
unset($array2[$key2]);
}
}
if (!empty($merged_array)) {
$result_array[] = $merged_array;
}
}
return array_merge($result_array, $array2);
}
$final_array = merge_on_key($array1, $array2, "b");
print_r($final_array);
In case you have to match the "b" index within the $array1 itself too, then simply use it twice:
$array1 = merge_on_key($array1, $array1, "b");
$final_array = merge_on_key($array1, $array2, "b");

i really have no idea what you want to achieve here - but based on your description the following code works
$arrA = [
0 =>
[
'a' => 'm1',
'b' => 'x2'
],
1 =>
[
'a' => 'n1',
'b' => 'y2'
]
];
$arrB = [
0 =>
[
'b' => 'x2',
'c' => 'p1',
],
1 =>
[
'b' => 'x2',
'd' => 'q1',
],
2 =>
[
'b' => 'y2',
'e' => 'r1',
],
];
foreach($arrB AS $arrData)
{
foreach($arrData AS $key => $val)
{
if ((isset($arrData['a']) && $arrData['a'] == $arrA[0]['a']) || (isset($arrData['b']) && $arrData['b'] == $arrA[0]['b']))
{
$arrA[0][$key] = $val;
}
elseif ((isset($arrData['b']) && $arrData['b'] == $arrA[1]['a']) || (isset($arrData['b']) && $arrData['b'] == $arrA[1]['b']))
{
$arrA[1][$key] = $val;
}
}
}
print_r($arrA);

Created the arrays similar to yours. $new_array is the resultant array that you are looking for.
$a=array();
$a[0]=array('a'=>'m1', 'b'=>'x2');
$a[1]=array('a'=>'n1', 'b'=>'y2');
$b=array();
$b[0]=array('b'=>'x2', 'c'=>'p1');
$b[1]=array('b'=>'x2', 'd'=>'q1');
$b[2]=array('b'=>'y2', 'e'=>'r1');
foreach($a as $row){
//echo '<pre>'; print_r($row);
foreach($b as $c=>$row1){
//echo '<pre>'; print_r($row1);echo $c;die;
if($row['b']==$row1['b']){
$new_array[]=array_merge($row, $row1);
}
}
}echo '<pre>'; print_r($new_array);

// Gather all values of b from both arrays
$all_b = array_unique(array_merge(array_column($arr1, 'b'), array_column($arr2, 'b')));
$res = [];
// For each b value
foreach($all_b as $b) {
$temp = [];
// Scan the arrays for items with the same b value
foreach($arr1 as $a1) {
if ($a1['b'] == $b) $temp = array_merge($temp, $a1);
}
foreach($arr2 as $a2) {
if ($a2['b'] == $b) $temp = array_merge($temp, $a2);
}
// Save them to new array
$res[] = $temp;
}
print_r($res);
demo on eval

Related

PHP combine key value array and regular array

I have 2 arrays:
array1 :
[0]=>
string(10) "AAAAAAAAAAA"
[1]=>
string(10) "BBBBBBBBBBB"
...
and array2:
[0]=>
float(0)
[550]=>
float(55)
...
I need a result like this:
"AAAAAAAAAAA" : 0 : 0
"BBBBBBBBBBB" : 550: 55
...
i.e. how to combine the arrays. How do i get that?
suppose you two arrays have the same length,
$keys = array_keys($array1);
$values = [];
foreach($array2 as $k=>$v)
{
$values[] = $k.':'.$v;
}
$result = array_combine($keys, $values);
The result you want is not clear... if each rows are just a string, this should work :
$a = [
0 => "AAAAAAAAAAA",
1 => "BBBBBBBBBBB"
];
$b = [
0 => (float) 0,
550 => (float) 55
];
$result = array_map(
function($v1, $v2, $v3) {
return "$v1 : $v2 : $v3";
},
$a, array_keys($b), $b
);
var_dump($result);

Reset array keys in multidimensional array, recursive, by reference

I want to reset keys in a big, multidimensional array. I already found a solution which is actually work:
$fix_keys = function(array $array) use (&$fix_keys)
{
foreach($array as $k => $val)
{
if (is_array($val))
{
$array[$k] = $fix_keys($val);
}
}
return array_values($array);
};
and the problem is, if I pass big arrays to it, it becomes slow and memory consuming. What about refactoring with working references:
$fix_keys = function(array &$array) use (&$fix_keys)
{
foreach($array as $k => &$val)
{
if (is_array($val))
{
$array[$k] = $fix_keys($val);
}
}
unset($val);
$array = array_values($array);
};
but it messed up the array, all I get is [0] => null. What is wrong?
Edit: so input data:
$a = [
'a' => 1,
'b' => 2,
'c' => [
'aa' => 11,
'bb' => [
'ccc' => 1
],
'cc' => 33
]
];
and I want to have:
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
array(3) {
[0]=>
int(11)
[1]=>
array(1) {
[0]=>
int(1)
}
[2]=>
int(33)
}
}
If memory is an issue you can try using yield. I'm not sure if this fits your needs, but here it is:
function reduce($array){
foreach($array as $key => $value){
if(is_array($value)){
reduce($value);
}
}
yield array_values($array);
}
You can also use send if you need to apply some logic to the generator.
I found the solution:
$fix_keys = function(array &$array) use (&$fix_keys)
{
foreach(array_keys($array) as $k)
{
if (is_array($array[$k]))
{
$fix_keys($array[$k]);
}
}
$array = array_values($array);
};

Convert multi-dimensional array key value

I have array like:-
$x = array(
'a' => array('aa' => array('aaa' => array(1, 2, 3))),
'b' => array('bb' => array('bbb' => array(1, 2, 3))),
);
Then, I want to modifying array to:-
$y = array(
1 => array('a', 'b'),
2 => array('aa', 'bb'),
3 => array('aaa', 'bbb'),
);
Please help me!
NB: if the last array 2,1,3 will be 2->a,b; 1->aa,bb; 3->aaa,bbb
You can try something like this:
$x = array(
'a' => array('aa' => array('aaa' => array(1, 2, 3))),
'b' => array('bb' => array('bbb' => array(1, 2, 3))),
);
$loop=true;
$item=array();
foreach ($x as $index => $value) {
if(!is_int($index)) $item[strlen($index)][]=$index;
while($loop){
foreach ($value as $sub_index => $sub_value) {
if (is_array($sub_value)) {
if(!is_int($sub_index)) $item[strlen($sub_index)][]=$sub_index;
$value=$sub_value;
}
else {
if(!is_int($sub_index))$item[strlen($sub_index)][]=$sub_index;
$loop=false;
}
}
}
$loop=true;
}
var_dump($item);
output
array(3) {
[1]=> array(2) { [0]=> string(1) "a" [1]=> string(1) "b" }
[2]=> array(2) { [0]=> string(2) "aa" [1]=> string(2) "bb" }
[3]=> array(2) { [0]=> string(3) "aaa" [1]=> string(3) "bbb" }
}
You could try the approach in the code below. And by the way, you could Quick-Test it Here.
<?php
$x = array(
'a' => array('aa' => array('aaa' => array(1, 2, 3))),
'b' => array('bb' => array('bbb' => array(1, 2, 3))),
);
$result = array();
$result[] = array_keys($x);
$tmp1 = [];
$tmp2 = [];
foreach($x as $k=>$arrData){
if(is_array($arrData)){
foreach($arrData as $k1=>$v1){
$tmp1[] = $k1;
if(is_array($v1)){
foreach($v1 as $k2=>$v2){
$tmp2[] = $k2;
}
}
}
}
}
$result[] = $tmp1;
$result[] = $tmp2;
var_dump($result);
//YIELDS:::
array (size=3)
0 =>
array (size=2)
0 => string 'a' (length=1)
1 => string 'b' (length=1)
1 =>
array (size=2)
0 => string 'aa' (length=2)
1 => string 'bb' (length=2)
2 =>
array (size=2)
0 => string 'aaa' (length=3)
1 => string 'bbb' (length=3)
Based on what you explained, I would suggest something like this:-
$x = array(
'a' => array('aa' => array('aaa' => array(1, 2, 3))),
'b' => array('bb' => array('bbb' => array(1, 2, 3))),
);
$y = array();
$l = array();
foreach ($x as $l[0] => $x2) {
foreach ($x2 as $l[1] => $x3) {
foreach ($x3 as $l[2] => $keys) {
for ($i = 0; $i < 3; $i++) {
if (isset($y[$keys[$i]])) {
$y[$keys[$i]][] = $l[$i];
} else {
$y[$keys[$i]] = array($l[$i]);
}
}
}
}
}
But please note that this code will fail if the depth changes or does not match the number of values that become keys...

Combining keys by similar values in PHP

I am trying to combine keys when they have similar values, and expect the result as a string. Actually I had no idea how to achieve this, although I run a few tests.
$array = array(
'a' => 65,
'b' => 31,
'c' => 100,
'd' => 31,
'e' => 31,
'f' => 31,
'h' => 23,
'i' => 23,
'j' => 23,
'k' => 23,
'l' => 48,
'm' => 48,
);
$results = array();
foreach ($array as $k => $v) {
// This is my attempt among others to no luck.
// Can not use array_key_exists because values are unpredictable.
$similars[$v] = $k;
$results[$v] = implode(", ", array_unique($similars)) . ' : ' . $v;
}
var_dump(implode("\n ", $results));
You can view the output:
http://codepad.org/ECekF3dq
I am almost there, but obviously wrong :(
Not expected:
string(72) "a : 65
a, f, c : 31
a, b, c : 100
a, f, c, k : 23
a, f, c, k, m : 48"
Expected:
a : 65
b, d, e, f : 31
c : 100
h, i, j, k : 23
l, m : 48
Those with the same values should collapse as one line.
Thanks for any hint.
You want to make $similars into an array of arrays. That way you can keep all the keys with that value.
$results = array();
$similars = array();
foreach ($array as $k => $v) {
if(!isset($similars[$v])){
$similars[$v] = array($k);
}
else{
$similars[$v][] = $k;
}
$results[$v] = implode(", ", $similars[$v]) . ' : ' . $v;
}
var_dump(implode("\n ", $results));
There might be a more elegant way of doing this, but I'd probably use two simple foreach loops:
function parseArray($data)
{
$tmp = array();
foreach ($data as $key => $item) {
// Check if we already created this key
if (isset($tmp[$item])) {
// Append if so
$tmp[$item] .= ', '.$key;
} else {
// Init if not
$tmp[$item] = $key;
}
}
// Now we stringify the tmp array.
$result = '';
foreach ($tmp as $key => $value) {
$result .= "$key : $value\n";
}
return $result;
}
$tmp = array();
foreach ($array as $k => $v) $tmp[$v][] = $k;
foreach ($tmp as $k => $v) echo implode(', ', $v) . ' : ' . $k . "\n<br />";
I think reversing the keys and values could be beneficial. Turn the integers into keys, and the chars into array values. This would enable you to maintain the desired one-to-many relationship:
$array = array(
'a' => 65,
'b' => 31,
'c' => 100,
'd' => 31,
'e' => 31,
'f' => 31,
'h' => 23,
'i' => 23,
'j' => 23,
'k' => 23,
'l' => 48,
'm' => 48,
);
$results = array();
foreach ($array as $k => $v) {
$results[$v][]=$k;
}
foreach ($results as $k=>$v) {
echo implode(',',$v) . " : " . $k . "\r\n";
}
the multidimensional array $results equals:
array(5) {
[65]=>
array(1) {
[0]=>
string(1) "a"
}
[31]=>
array(4) {
[0]=>
string(1) "b"
[1]=>
string(1) "d"
[2]=>
string(1) "e"
[3]=>
string(1) "f"
}
[100]=>
array(1) {
[0]=>
string(1) "c"
}
[23]=>
array(4) {
[0]=>
string(1) "h"
[1]=>
string(1) "i"
[2]=>
string(1) "j"
[3]=>
string(1) "k"
}
[48]=>
array(2) {
[0]=>
string(1) "l"
[1]=>
string(1) "m"
}
}
Final output:
a : 65
b,d,e,f : 31
c : 100
h,i,j,k : 23
l,m : 48
Try this
$array = array('a' => 65,'b' => 31,'c' => 100,'d' => 31,'e' => 31,'f' => 31,'h' => 23,
'i' => 23,'j' => 23,'k' => 23,'l' => 48,'m' => 48);
$similars = array();
foreach ($array as $k => $v) {
// This is my attempt among others to no luck.
// Can not use array_key_exists because values are unpredictable.
$key = array_search($v, $similars);
if (isset($similars[$key])) {
unset($similars[$key]);
$similars[$key.','.$k] = $v;
}
else
$similars[$k] = $v;
}
print_r($similars);
//display as expected
foreach($similars as $k => $v)
echo "</br>".$k.':'.$v;

PHP: Check for duplicate values in a multidimensional array

I have this issue with multidimensional arrays.
Given the following multidimensional array:
Array(
[0] => Array("a", "b", "c")
[1] => Array("x", "y", "z")
[2] => Array("a", "b", "c")
[3] => Array("a", "b", "c")
[4] => Array("a", "x", "z")
)
I want to check its values and find duplicates (i.e. keys 0, 2 and 3) leaving just one key - value pair deleting the others, resulting in somthing like this:
Array(
[0] => Array("a", "b", "c")
[1] => Array("x", "y", "z")
[2] => Array("a", "x", "z")
)
How can I do that??
This will remove duplicate items from your array using array_unique():
$new_arr = array_unique($arr, SORT_REGULAR);
You can simply do it using in_array()
$data = Array(
0 => Array("a", "b", "c"),
1 => Array("x", "y", "z"),
2 => Array("a", "b", "c"),
3 => Array("a", "b", "c"),
4 => Array("a", "x", "z"),
);
$final = array();
foreach ($data as $array) {
if(!in_array($array, $final)){
$final[] = $array;
}
}
which will get you something like
array(3) {
[0] => array(3) {
[0] => string(1) "a"
[1] => string(1) "b"
[2] => string(1) "c"
}
[1] => array(3) {
[0] => string(1) "x"
[1] => string(1) "y"
[2] => string(1) "z"
}
[2] => array(3) {
[0] => string(1) "a"
[1] => string(1) "x"
[2] => string(1) "z"
}
}
You can go smart with serialization for comparison of arrays.
var_dump(makeUnique($data));
function makeUnique(array $data)
{
$serialized = array_map(create_function('$a', 'return serialize($a);'), $data);
$unique = array_unique($serialized);
return array_intersect_key($unique, $data);
}
Have fun
$arr = ...;
$final = array();
sort($arr);
foreach ($arr as $el) {
if (!isset($prev) || $el !== $prev)
$final[] = $el
$prev = $el;
}
This is a more efficient1 solution (log n + n instead of quadratic) but it relies on a total order between all the elements of the array, which you may not have (e.g. if the inner arrays have objects).
1 More efficient than using in_array. Turns out array_unique actually uses this algorithm, so it has the same shortcomings.
To check using array_unique on multidimensional arrays, you need to flatten it out like so, using implode.
$c=count($array)
for($i=0;$i<$c;$i++)
{
$flattened=implode("~",$array[$i]);
$newarray[$i]=$flattened;
}
if(count(array_unique($newarray)
<count($newarray))
{
//returns true if $array contains duplicates
//can also use array_unique on $newarray
//to remove duplicates, then explode,
//to return to default state
}
Hope this is helpful, took sometime to get it.
**This is example array**
$multi_com=[
[
{
"combination_id": "19"
},
{
"combination_id": "20"
},
{
"combination_id": "21"
}
],
[
{
"combination_id": "18"
},
{
"combination_id": "20"
},
{
"combination_id": "22"
}
],
[
{
"combination_id": "20"
},
{
"combination_id": "21"
}
]
]
**This is sample code**
$array1 = [];
$array2 = [];
$status = false;
foreach ($multi_com as $key => $val) {
foreach ($val as $key2 => $val2) {
if (count($array1) !== 0) {
$array_res = in_array($val2->combination_id, $array1);
if ($array_res) {
$array2[] = $val2->combination_id;
}
}
}
if (!$status) {
for ($x = 0; $x < count($val); $x++) {
$array1[] = $val[$x]->combination_id;
}
} else {
$array1 = [];
$array1 = $array2;
$array2 = [];
}
$status = true;
}
return $array1;

Categories