PHP converting simple array to more complex associative array - php

My selection from DB returns this:
Array
(
[0] => Array
(
[bin_full] => AA010101
[letter1_zone] => A
[letter2_aisle] => A
[letter34_bay] => 01
[letter56_level] => 01
[letter78_bin] => 01
)
[1] => Array
(
[bin_full] => AA010102
[letter1_zone] => A
[letter2_aisle] => A
[letter34_bay] => 01
[letter56_level] => 01
[letter78_bin] => 02
)
[2] => Array
(
[bin_full] => AA010201
[letter1_zone] => A
[letter2_aisle] => A
[letter34_bay] => 01
[letter56_level] => 02
[letter78_bin] => 01
)
As you can see, its basically the first item bin_full, being broken up into first letter, second letter, then next 2 numbers, next 2 numbers and finally the last 2 numbers. The pattern is the same, I need each level grouped together in an assoc array.
If I then do this, I'm mostly getting the result I want, but it needs a tweak and I'm not sure how to do that..
foreach ($data_full as $row) {
foreach ($row as $key2 => $value2) {
$data_array[$row['letter1_zone']][$row['letter2_aisle']][$row['letter34_bay']][$row['letter56_level']][$row['letter78_bin']] = $value2;
}
}
This results in:
Array
(
[A] => Array
(
[A] => Array
(
[01] => Array
(
[01] => Array
(
[01] => 01
[02] => 02
)
[02] => Array
(
[01] => 01
[02] => 02
)
[03] => Array
(
[01] => 01
)
)
)
)
)
I need the last array to be:
[0] => 01
[1] => 02
not
[01] => 01
[02] => 02
In full, I need this:
Array
(
[A] => Array
(
[A] => Array
(
[01] => Array
(
[01] => Array
(
[0] => 01
[1] => 02
)
[02] => Array
(
[0] => 01
[1] => 02
)
[03] => Array
(
[0] => 01
)
)
)
)
)
Thanks

All you have to do is replace this :
foreach ($data_full as $row) {
foreach ($row as $key2 => $value2) {
$data_array[$row['letter1_zone']][$row['letter2_aisle']][$row['letter34_bay']][$row['letter56_level']][$row['letter78_bin']] = $value2;
}
}
with this :
foreach ($data_full as $row) {
$data_array[$row['letter1_zone']][$row['letter2_aisle']][$row['letter34_bay']][$row['letter56_level']][] = $row['letter78_bin'];
}
so you replace the last index with a "add new element": []. It will first add index 0, then 1, then 2, etc...

$data_array[$row['letter1_zone']][$row['letter2_aisle']][$row['letter34_bay']][$row['letter56_level']][] = $value2;

Related

How to sort a multidimensional array by alphanumeric value?

I have an array like this below,
Array
(
[2] => Array
(
[id] => 75
[program] => Apr 2020-Nov 2020
)
[1] => Array
(
[id] => 73
[program] => Feb 2016-Aug 2020
)
[0] => Array
(
[id] => 72
[program] => May 2020-Dec 2020
)
)
The resultant array should be
Array
(
[1] => Array
(
[id] => 73
[current_program] => Feb 2016-Aug 2020
)
[2] => Array
(
[id] => 75
[current_program] => Apr 2020-Nov 2020
)
[0] => Array
(
[id] => 72
[current_program] => May 2020-Dec 2020
)
)
It should sort based on the year. I have tried to achieve by "strnatcasecmp", but the array is sorting by alphabet not by the numeric value in it
usort($programp, function($a, $b) {
return strnatcasecmp($a['program'], $b['program']);
});
Any help would be appreciated!
Thanks
You need to convert the first month and year into a timestamp, sort that thereby sorting the original:
foreach($programp as $values) {
$starts[] = strtotime(explode('-', $values['program'])[0]);
}
array_multisort($starts, $programp);
Before sorting the $starts array would look like this, easy to sort:
Array
(
[0] => 1585692000
[1] => 1454281200
[2] => 1588284000
)
You probably want some error checking to make sure $values['program'] is not empty etc...
//Sort indexes so the keys are 0,1,2 instead of 1,2,0
//This is important when sorting down below with asort()
$arr = array_values($arr);
//Go through every "program" (dateinterval in your array)
//and make a new array in the format year-monthnr
//Date parse returns the number of jan(1),feb(2),mar(3) etc..
$year_month = [];
foreach(array_column($arr,'program') as $key => $item) {
$year = explode(' ', explode('-',$item)[0])[1];
$month = date_parse(explode(' ', explode('-',$item)[0])[0])['month'];
$year_month[] = $year . '-' . $month;
}
//Sort with mainted indexes (keys)
asort($year_month);
//Create new array "mapped" keys to the original array $arr
$new_arr = [];
foreach($year_month as $key=>$item) {
$new_arr[] = $arr[$key];
}
Output of $new_arr would be:
Array
(
[0] => Array
(
[id] => 73
[program] => Feb 2016-Aug 2020
)
[1] => Array
(
[id] => 75
[program] => Apr 2020-Nov 2020
)
[2] => Array
(
[id] => 72
[program] => May 2020-Dec 2020
)
)

Combine 3 level multi dimensional array according to index

I have an array.in which i want to combine value according to same index value of sub array.it's a multi dimensional dynamic array which contain some same and some different indexes like sports footer etc.Please check the below array
Array
(
[0] => Array
(
[0] => Array
(
[Sport] => 15
)
[1] => Array
(
[Sport] => 14
)
[2] => Array
(
[Sport] => 29
)
)
[1] => Array
(
[0] => Array
(
[Surgical] => 11
)
[1] => Array
(
[Surgical] => 12
)
[2] => Array
(
[Surgical] => 13
)
[3] => Array
(
[Footwear] => 10
)
)
)
Below it the array format which i want as an output
Array
(
[0] => Array
(
[0] => 15
[1] => 14
[2] => 29
)
[1] => Array
(
[0] => 11
[1] => 12
[2] => 13
),
[2] => Array(
[0] => 10
)
)
Assuming your input array is called $data, you could do this:
foreach ($data as $row) {
foreach ($row as $pair) {
foreach ($pair as $key => $value) {
$result[$key][] = $value;
}
}
}
This will provide the $result as follows:
[
"Sport" => [15, 14, 29],
"Surgical" => [11, 12, 13],
"Footwear" => [10]
]
If you really want to throw away the "labels" and just keep the values, then add the following conversion at the end:
$result = array_values($result);
Which will give you the desired result:
[
[15, 14, 29],
[11, 12, 13],
[10]
]
... but that would seem less useful to me.

Switch nested array values with keys, and reverse tally accordingly

I've taken a few photographs and I've tagged people as being in them. I have an array whose keys are photo_id's and whose values are arrays of person_id's tagged in the photograph:
Array
(
[19] => Array
(
[0] => 12
)
[21] => Array
(
[0] => 177
)
[26] => Array
(
[0] => 27
[1] => 4
)
[27] => Array
(
[0] => 27
[1] => 4
)
[28] => Array
(
[0] => 934
[1] => 935
[2] => 234
)
)
What I want is an array with the person_id's as keys and the photographs they are tagged in as values. For example, person 27 is in photographs 26 and 27. How would I go about creating this new array? Thank you so much!
You'll simply need to loop over your array and create a new array using the person_id as your new key and n number of entries which are your photo_ids:
$new_array = array();
foreach($original_array as $photo_id => $values) {
foreach($values as $person_id) {
// initialize array key if it doesn't already exist
if(!array_key_exists($person_id, $new_array)) {
$new_array[$person_id] = array();
}
// add photo id to the array
$new_array[$person_id][] = $photo_id;
}
}
Here's a demo: https://eval.in/147879
You can use a combination of array_walk() and in_array() to get what you need done:
$pictures = Array( 19 => [12], 21 => [177], 26 => [27,4], 27 => [27,4], 28 => [934,935,234] );
$included = [];
$person = 27;
//The following line is all you need
array_walk( $pictures, function(&$picture, $pictureId, $params) {
if( in_array( $params[1], $picture, TRUE ) )
array_push( $params[0], $pictureId );
}, [&$included, $person] );
print_r( $included );
Will print out:
Array
(
[0] => 26
[1] => 27
)
If you want to completely reverse the array, then you can use double foreach loops to iterate through them:
$pictures = [19 => [12], 21 => [177], 26 => [27,4], 27 => [27,4], 28 => [934,935,234] ];
$included = [];
foreach( $pictures as $pictureId => $picture ) {
foreach( $picture as $personId ) {
if( !isset( $included[$personId] ) )
$included[$personId] = [];
array_push( $included[$personId], $pictureId );
}
};
print_r( $included );
The result of this will print:
Array
(
[12] => Array
(
[0] => 19
)
[177] => Array
(
[0] => 21
)
[27] => Array
(
[0] => 26
[1] => 27
)
[4] => Array
(
[0] => 26
[1] => 27
)
[934] => Array
(
[0] => 28
)
[935] => Array
(
[0] => 28
)
[234] => Array
(
[0] => 28
)
)

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;
}

Transform Array from Key/Value to Multi Dimensional

this may seem a rather trivial question, please excuse my ignorance. Still getting the hang of array manipulation...
I have a CakePHP app that is posting an array to my controller to be saved. I need to somehow reformat the sent array so that it may be processed properly by Cake's Save behaviour.
The array posted is:
Array (
[788] => Array ( [id] => 788 )
[787] => Array ( [id] => 787 )
[786] => Array ( [id] => 0 )
[785] => Array ( [id] => 0 )
[value_1] => 0
[analysed_date] => Array (
[month] => 08
[day] => 16
[year] => 2011
)
[job_id] => 34
)
Desired Array:
Array (
[0] => Array (
[id] => 788
[value_1] => 0
[analysed_date] => Array (
[month] => 08
[day] => 16
[year] => 2011
)
)
[1] => Array (
[id] => 787
[value_1] => 0
[analysed_date] => Array (
[month] => 08
[day] => 16
[year] => 2011
)
)
)
Thanks for taking the time to look.
EDIT:
I've just realised I omitted the fact that if the array has an [id] => 0 that it needs to be ignored. This was my primary stumbling block. Apologies. I hope the edit clarifies my problem better.
SOLVED
Thank you for your help guys. I was able to come up with the solution by myself. Here is what I came up with.
foreach($org_array as $key => $value){
if(is_array($value)){
if(isset($value['id'])){
if($value['id'] != 0) {
$data[$i] = array(
'id' => $value['id'],
'value_1'=> $value_1,
'analysed_date' => $date
);
$i++;
}
}
}
}
Something like this should work, but just for your example:
$array_keys = array_keys($org_array);
$new_array = array();
foreach ($array_keys as $key)
{
if (is_int($key))
{
$new_array[] = array(
"id" => $key,
"value1" => $org_array["value1"],
"analysed_date" => $org_array["analysed_date"]
);
// you might want to loop throught the original array to get all non-integer key values instead of hard-coding it
}
}
$main = Array (
[788] => Array ( [id] => 788 )
[787] => Array ( [id] => 787 )
[786] => Array ( [id] => 786 )
[785] => Array ( [id] => 785 )
[value_1] => 0
[analysed_date] => Array (
[month] => 08
[day] => 16
[year] => 2011
)
[job_id] => 34
)
$analysed_date = $main['analysed_date'];
$value1 = $main['value_1'];
$result = array();
$i=0;
foreach($main as $key=>$value)
{
if( is_numeric($key)
{
$result[$i]=array();
$result[$i]['id']=$key;
$result[$i]['value_1']=$value1;
$result[$i]['analysed_date']=$analysed_date;
$i++;
}
}

Categories