Sync array values across all related array keys - php

I have a PHP array with the following data
Array
(
[3] => Array
(
[0] => 4095
[2] => 651
)
[4095] => Array
(
[0] => 3
)
[651] => Array
(
[0] => 4432
)
[4432] => Array
(
[0] => 651
)
[92] => Array
(
[0] => 45
)
)
The above array has keys as student_id and the values are also student_id creating a circular relation. What I am trying to achieve is all the student_id has the same set of student_id values. Basically if student_id 3 is related to 4095, 4432 & 651, then, in turn, each of these values has to have 3 among them including other student_id from 3. The below output demonstrates what I am trying to achieve.
Array
(
[3] => Array
(
[0] => 4095
[1] => 4432
[2] => 651
)
[4095] => Array
(
[0] => 3
[1] => 4432
[2] => 651
)
[651] => Array
(
[0] => 3
[1] => 4432
[2] => 4095
)
[4432] => Array
(
[0] => 3
[1] => 4095
[2] => 651
)
[92] => Array
(
[0] => 45
)
[45] => Array
(
[0] => 92
)
)
Explanation of output
The array keys 3, 4095, 651 & 4432 are related to each other either directly or via a common relation (indirect), so will have common set of values (siblings). The key 92 in input array has a value (sibling) of 45, so in a resultant array, a new key 45 will be added to array with the inverse relation as well.
What I have tried so far
I have tried to do it with this code
$syncedSiblings = [];
foreach ($studentsWithSiblings as $sid => $siblings) {
$all = map_assoc(array_merge([$sid], array_keys($siblings)));
foreach ($all as $studentId) {
if (isset($syncedSiblings[$studentId])) {
$old = $syncedSiblings[$studentId];
$syncedSiblings[$studentId] = array_unique(array_merge($old, array_except($all, $studentId)));
} else {
$syncedSiblings[$studentId] = array_unique(array_except($all, $studentId));
}
}
}
Where $studentsWithSiblings has the above array & array_except returns array without the passed values as second argument.
This is the output I am getting right now
Array
(
[3] => Array
(
[0] => 4095
[1] => 651
)
[4095] => Array
(
[0] => 3
[1] => 651
)
[651] => Array
(
[0] => 3
[1] => 4095
[2] => 4432
)
[4432] => Array
(
[0] => 651
)
[92] => Array
(
[0] => 45
)
)
Any help with this will be highly appreciated.

If I've understood you correctly, then this possible to achieve with recursion:
function getChildren($ind_ar, $prev_ar, $data, $rem){
$tmp = [];
$mark = 0;
foreach($ind_ar as $ind){
foreach($data[$ind] as $new_val){
if(!in_array($new_val,$prev_ar) && $new_val != $ind && $new_val != $rem){
$mark = 1;
$tmp[] = $new_val;
}
foreach($data[$new_val] as $new){
if(!in_array($new,$prev_ar) && $new != $ind && $new != $rem){
$mark = 1;
$tmp[] = $new;
}
}
}
}
$res_ar = $prev_ar;
if(!empty($tmp)) $res_ar = array_unique(array_merge($tmp,$prev_ar));
if($mark) $res_ar = getChildren($tmp,$res_ar,$data, $rem);
return $res_ar;
}
You can use this function in this way:
$data = array( 3 => [4095, 651], 4095 => [3], 651 => [4432], 4432 => [3, 651], 92 => [45], 45 => [92], );
foreach($data as $in => &$data_val) {
$data_val = getChildren([$in],$data_val,$data, $in);
sort($data_val);
}
Demo
Output:
Array
(
[3] => Array
(
[0] => 651
[1] => 4095
[2] => 4432
)
[4095] => Array
(
[0] => 3
[1] => 651
[2] => 4432
)
[651] => Array
(
[0] => 3
[1] => 4095
[2] => 4432
)
[4432] => Array
(
[0] => 3
[1] => 651
[2] => 4095
)
[92] => Array
(
[0] => 45
)
[45] => Array
(
[0] => 92
)
)

Two nested loops over the data. If the keys are different, then check if the key of the inner loop is already contained in the data array of the outer key element - if not, add it.
$data = json_decode('{"3":{"0":4095,"2":651},"4095":[3],"651":[4432],"4432":{"1":651}}', true);
foreach($data as $key_outer => $val_outer) {
foreach($data as $key_inner => $val_inner) {
if($key_outer != $key_inner && !in_array($key_inner, $data[$key_outer])) {
$data[$key_outer][] = $key_inner;
}
}
}
var_dump($data);
This gets you
array (size=4)
3 =>
array (size=3)
0 => int 4095
2 => int 651
3 => int 4432
4095 =>
array (size=3)
0 => int 3
1 => int 651
2 => int 4432
651 =>
array (size=3)
0 => int 4432
1 => int 3
2 => int 4095
4432 =>
array (size=3)
1 => int 651
2 => int 3
3 => int 4095
I am assuming a specific order of the elements in those sub-items is not actually required. If it is, then please sort them yourself as desired afterwards or in between (depending on what exactly you need, f.e. sort($data[$key_outer]); after the inner loop would get you the IDs in all sub-arrays sorted ascending.)

Related

Collecting values from a multidimensional array using foreach loops

There is an array which is built looks like the following (with some more values which i left away for this example):
Array
(
[0] => Array
(
[id] => 44
[cars] => Array
(
[0] => Array
(
[id] => 38
)
[1] Array
(
[id] => 39
)
)
)
[1] => Array
(
[id] => 45
[cars] => Array
(
[0] => Array
(
[id] =>136
)
[1] =>Array
(
[id] =>137
)
[2] =>Array
(
[id] =>138
)
)
)
)
I want to build another array from the above in the following form:
Array
(
[0] => Array
(
['car_filter_sort_id'] => 44
['car_id'] => 38
)
[1] => Array
(
['car_filter_sort_id'] => 44
['car_id'] => 39
)
[2] => Array
(
['car_filter_sort_id'] => 45
['car_id'] => 136
)
[3] => Array
(
['car_filter_sort_id'] => 45
['car_id'] => 137
)
[4] => Array
(
['car_filter_sort_id'] => 45
['car_id'] => 138
)
)
I tried to achieve this with following function:
foreach($filterSortSaveArray as $filterSortSaveArray['cars'] => $value){
$id = $filterSortSaveArray['id'];
foreach($value['cars'] as $value => $car){
$field_values['car_filter_sort_id'] = $id;
$field_values['car_id'] = $car['id'];
}
}
But the the result differs from what I have expected. Any suggestions?
There are two big issues in your code. First, are you referencing undefined value with $filterSortSaveArray['cars'], since there is no 'cars' key in the first level of the original array. Second, by assigning values to $field_values['car_filter_sort_id'] and $field_values['car_id'] in the loop you are just overriding them in each iteration. You need to push the values into an array using []= operator (which is equivalent to applying array_push()).
Try this:
$result = [];
foreach($filterSortSaveArray as $k => $v) {
if (!is_array($v['cars']))
continue;
$id = $v['id'];
foreach ($v['cars'] as $i => $car){
$result[] = [
'car_filter_sort_id' => $id,
'car_id' => $car['id']
];
}
}

count same categories from array and Store in new array with its count and category name

I have one array which I am getting from database query response.
Now I want to count same categories and print in option_name array.
I have tried it with different array functions but want get desire output.
I have one idea to take new array and push it with foreach loop but not much idea of how can i achieve using code. Please help me to solve it.
Array
(
[0] => Array
(
[CNC] => Array
(
[id] => 5
[category_id] => 68
)
[GVO] => Array
(
[option_name] => Actors
)
)
[1] => Array
(
[CNC] => Array
(
[id] => 11
[category_id] => 72
)
[GVO] => Array
(
[option_name] => Cricketers
)
)
[2] => Array
(
[CNC] => Array
(
[id] => 3
[category_id] => 72
)
[GVO] => Array
(
[option_name] => Cricketers
)
)
[3] => Array
(
[CNC] => Array
(
[id] => 4
[category_id] => 74
)
[GVO] => Array
(
[option_name] => Musician
)
)
[4] => Array
(
[CNC] => Array
(
[id] => 7
[category_id] => 76
)
[GVO] => Array
(
[option_name] => Directors
)
)
[5] => Array
(
[CNC] => Array
(
[id] => 6
[category_id] => 76
)
[GVO] => Array
(
[option_name] => Directors
)
)
)
Desire Output:
Array
(
[Actors] => 1
[Cricketers] => 2
[Musician] => 1
[Directors] => 2
)
Thanks in advance!
You simply need to loop through the array using foreach like as
$result = [];
foreach($arr as $k => $v){
if(isset($result[$v['GVO']['option_name']])){
$result[$v['GVO']['option_name']] += 1;
}else{
$result[$v['GVO']['option_name']] = 1;
}
}
print_R($result);
You can count the option_name values by incrementing a counter in an associative array where the key is the option_name:
$counts = [];
foreach($array as $v) {
if(!isset($counts[$v['GVO']['option_name']])) {
$counts[$v['GVO']['option_name']] = 0;
}
$counts[$v['GVO']['option_name']]++;
}
print_r($counts);
Try this:
$new_arr = array();
foreach(array_column($your_arr, 'option_name') as $value){
if(in_array($value, $new_array)){
$new_array[$value] = $new_array[$value]+1;
}else{
$new_array[$value] = 1;
}
}
Output
Array
(
[Actors] => 1
[Cricketers] => 2
[Musician] => 1
[Directors] => 2
)

Overwrite subarrays in one multidimensional array if different from another multidimensional array

I stuck on this and really don't know how to solve it.
I have two multi-dimensional arrays and need to match every "entry_id" from second array with first one. Then need to check if every "file_no" from second array is in database (first array) and "status" are matched with 1st array . If "status" is different, update second array with string (e.g. updated value) like this:
...
[status] => Array
(
[0] => abc
[1] => defghijk - "updated value"
)
So I have first array from database:
Array
(
[0] => Array
(
[entry_id] => 1
[file_no] => KSBR 40 INS 3674 / 2014
[status] => abc
)
[1] => Array
(
[entry_id] => 9
[file_no] => KSUL 77 INS 18898 / 2013
[status] => abc
)
[2] => Array
(
[entry_id] => 9
[file_no] => KSUL 77 INS 21218 / 2013
[status] => defg
)
)
And second array generated from script:
Array
(
[0] => Array
(
[entry_id] => 1
[id] => 500910/098
[fullname] => Milan Vrtal
[type] => person
[file_no] => Array
(
[0] => KSBR 26 INS 37146 / 2013
[1] => KSBR 40 INS 3674 / 2014
)
[status] => Array
(
[0] => status1
[1] => status2
)
)
[1] => Array
(
[entry_id] => 2
[id] => 46900217
[fullname] => ENTEC a.s.
[type] => company
[file_no] => Array
(
[0] => KSBR 28 INS 1232 / 2013
)
[status] => Array
(
[0] => qwer
)
)
[2] => Array
(
[entry_id] => 9
[fullname] => Blanka Kořínková
[type] => person
[file_no] => Array
(
[0] => KSUL 77 INS 18898 / 2013
[1] => KSUL 77 INS 21218 / 2013
)
[status] => Array
(
[0] => abc
[1] => defghijk
)
)
)
Thanks for every comment and sorry for english :)
This is by creating a temporary array to search in. This will use quite some memory when the arrays are big, but will result in faster execution time...
$tmparr = array();
foreach($arr1 as $arr1_val)
{
//put an new element in $temparr with key 'entry_id' and an array as value
if (!isset($tmparr[$arr1_val['entry_id']]))
$tmparr[$arr1_val['entry_id']] = array();
//add the status to the array
$tmparr[$arr1_val['entry_id']][] = $arr1_val['status'];
}
/*
$tmparr = Array
(
[1] => Array
(
[0] => abc
)
[9] => Array
(
[0] => abc
[1] => defg
)
)
*/
//arr2_val by reference so that we can change it
foreach($arr2 as &$arr2_val)
{
//get the current entry_id
$entry_id = $arr2_val['entry_id'];
//see if this entry_id was in the first array, and if so...
if (isset($tmparr[$entry_id]))
{
//change the status to both the original status and the status of the first array
$arr2_val['status'] = array_merge($arr2_val['status'],$tmparr[$entry_id]);
}
}
print_r($arr2);
Output:
Array
(
[0] => Array
(
[entry_id] => 1
[id] => 500910/098
[fullname] => Milan Vrtal
[type] => person
[file_no] => Array
(
[0] => KSBR 26 INS 37146 / 2013
[1] => KSBR 40 INS 3674 / 2014
)
[status] => Array
(
[0] => status1
[1] => status2
[2] => abc
)
)
[1] => Array
(
[entry_id] => 2
[id] => 46900217
[fullname] => ENTEC a.s.
[type] => company
[file_no] => Array
(
[0] => KSBR 28 INS 1232 / 2013
)
[status] => Array
(
[0] => qwer
)
)
[2] => Array
(
[entry_id] => 9
[fullname] => Blanka Kořínková
[type] => person
[file_no] => Array
(
[0] => KSUL 77 INS 18898 / 2013
[1] => KSUL 77 INS 21218 / 2013
)
[status] => Array
(
[0] => abc
[1] => defghijk
[2] => abc
[3] => defg
)
)
)
edit: This is possible too, whitout the temp array, but with a loop in a loop. This will be slower than the first one, but will consume less memory:
//arr2_val by reference so that we can change it
foreach($arr2 as &$arr2_val)
{
//get the current entry_id
$entry_id = $arr2_val['entry_id'];
//search for the correct row in the first array
foreach($arr1 as $arr1_val)
{
if ($arr1_val['entry_id'] == $arr2_val['entry_id'])
{
$arr2_val['status'][] = $arr1_val['status'];
//a continue should be added here to make it faster...
}
}
}
print_r($arr2);
This should work
foreach($array1 as $i)
{
foreach($array2 as $key=>$j)
{
if($j['entry_id'] == $i['entry_id'])
{
if($array2[$key]['status'] != $i['status'])
{
$j['status'] = array(
$i['status'],
$j['status'] // the new status
);
}
continue;
}
}
}
I found a solution for you :
$a1 = [['entry_id' => 1, 'file_no' => 'KSBR', 'status' => 'abc'], ['entry_id' => 2, 'file_no' => 'KSUL', 'status' => 'defg']];
$a2 = [['entry_id' => 1, 'file_no' => 'KSBR', 'status' => 'abc', 'type' => 'person'], ['entry_id' => 2, 'file_no' => 'KSUL', 'status' => 'defg']];
print_r(new_array_merge_recursive($a1, $a2));
function new_array_merge_recursive(array $array1, array $array2=array())
{
$arrays = func_get_args();
$merge = array_shift($arrays);
foreach ($arrays as $array)
{
foreach ($array as $key => $val)
{
if (is_array($val) && array_key_exists($key, $merge))
{
$val = new_array_merge_recursive((array) $merge[$key], $val);
}
$merge[$key] = $val;
}
}
return $merge;
}

how to merge key array on array

and i got a problem (its big for me) :(
ok, i have some array like ...
Array(
[0] => Array
(
[id] => 1
[order_sn] => EU/2011/04/PO/5
[total] => 65
)
[1] => Array
(
[id] => 1
[order_sn] => EU/2011/04/RS/4
[total] => 230
)
[2] => Array
(
[id] => 1
[order_sn] => EU/2011/04/RS/3
[total] => 130
)
[3] => Array
(
[id] => 2
[order_sn] => EU/2011/04/RS/2
[total] => 100
)
[4] => Array
(
[id] => 2
[order_sn] => EU/2011/04/RS/1
[total] => 60
)
)
how to merge them if the array have same key value ... ?
the result that i need got is like this ...
Array(
[0] => Array
(
[id] => 1
[detail] => Array
(
[0] => Array
(
[order_sn] => EU/2011/04/PO/5
[total] => 65
)
[1] => Array
(
[order_sn] => EU/2011/04/RS/4
[total] => 230
)
[2] => Array
(
[order_sn] => EU/2011/04/RS/3
[total] => 130
)
)
)
[2] => Array
(
[id] => 2
[detail] => Array
(
[0] => Array
(
[order_sn] => EU/2011/04/RS/2
[total] => 100
)
[1] => Array
(
[order_sn] => EU/2011/04/RS/1
[total] => 60
)
)
)
)
im very need some help here, and im working on PHP ... what method should i do for this case?
i try too searching on google and in here ... but i dont know the keyword >.<
Many thanks before :)
regard, Stecy
Try like this:
<?php
$result = array();
foreach ($my_array as $v) {
$id = $v['id'];
$result[$id]['id'] = $id;
$result[$id]['detail'][] = array(
'order_sn' => $v['order_sn'],
'total' => $v['total'],
);
}
You can just loop over the array and build a resulting one:
// $a is your array
$r=array();
foreach($a as $v)
$r[$v['id']][]=array('order_sn'=>$v['order_sn'], 'total'=>$v['total']);
echo'<pre>';
var_dump($r);
Since you do the paring by ID, it is wise to have it as the key and all the data associated with it as the value. There's no need to also have id and detail.
foreach($origianlArray as $key => $value){
$newArray[$value['id']]['id'] = $value['id'];
$newArray[$value['id']]['detail'][] = array('order_sn' => $value['order_sn'], 'total' => $value['total']);
}
Check out the PHP array_merge function.

How do i merge the arrays in a particular format?

I have following arrays:
1) for total placed
Array
(
[0] => Array
(
[centers] => Array
(
[name] => delhi
[id] => 1
)
[0] => Array
(
[totalplaced] => 8
)
)
[1] => Array
(
[centers] => Array
(
[name] => mumbai
[id] => 2
)
[0] => Array
(
[totalplaced] => 1
)
)
)
2) for total working
Array
(
[0] => Array
(
[centers] => Array
(
[name] => delhi
[id] => 1
)
[0] => Array
(
[totalworking] => 4
)
)
[1] => Array
(
[centers] => Array
(
[name] => mumbai
[id] => 2
)
[0] => Array
(
[totalworking] => 1
)
)
)
3) for total trained
Array
(
[0] => Array
(
[centers] => Array
(
[name] => delhi
[id] => 1
)
[0] => Array
(
[totaltrained] => 8
)
)
[1] => Array
(
[centers] => Array
(
[name] => mumbai
[id] => 2
)
[0] => Array
(
[totaltrained] => 1
)
)
)
I wanted to merge these arrays so that the resultant array should look like this
[newarray] => Array(
[0] => Array (
[centers] => Array
(
[name] => delhi
[id] => 1
[totalplaced] => 8
[totalworking] => 4
[totaltrained] => 8
)
)
[1]=> Array(
[centers] => Array
(
[name] => mumbai
[id] => 2
[totalplaced] => 1
[totalworking] => 1
[totaltrained] => 1
)
)
)
This is the tabular representation of the above data which i want to display
centername totalplaced totalworking totaltrained
delhi 8 4 8
mumbai 1 1 1
Please help me on this.
Thanks
Pankaj Khurana
The difficulty here is that PHP's functions such as array_merge() and array_merge_recursive() will not merge data into numeric keys, but rather will re-key any duplicate numeric key. So for example given two arrays:
array(
'test' => 'abc',
0 => 'xyz'
);
array(
'test' => 'def',
0 => 'uvw'
);
Merging them together with array_merge() will produce an array like:
array(
'test' => 'def',
0 => 'xyz',
1 => 'uvw'
);
So, you need a custom function to be "additive" on any key, regardless of whether it is a string or numeric key. Try this:
function mixed_key_array_merge() {
$args = func_get_args();
$result = array();
foreach ($args as $arg) {
// discard non-array arguments; maybe this could be better handled
if (!is_array($arg)) {
continue;
}
foreach ($arg as $key => $value) {
if (!isset($result[$key])) {
$result[$key] = $value;
} else if (is_array($result[$key])) {
$result[$key] = call_user_func_array('mixed_key_array_merge',array($result[$key],$value));
}
}
}
return $result;
}

Categories