Issue with recursive loop and nested multidimensional array - php

I have here a nested multidimensional array:
Array
(
[merchant] => Array
(
[XML_Serializer_Tag] => Array
(
[id] => 736
[name] => Cadbury Gifts Direct
)
[prod] => Array
(
[XML_Serializer_Tag] => Array
(
[0] => Array
(
[XML_Serializer_Tag] => Array
(
[id] => 88966064
[pre_order] => no
[web_offer] => no
[in_stock] => no
[stock_quantity] => 0
)
[pId] => 608
[isbn] => 0000000000000
[text] => Array
(
[name] => 50% OFF 56g Creme Egg Minis
[desc] => 50% OFF Creme Egg Minis in a 56g bag.
)
[uri] => Array
(
[awTrack] => http://www.awin1.com/pclick.php?p=88966064&a=67702&m=736
[awThumb] => http://images.productserve.com/thumb/736/88966064.jpg
[awImage] => http://images.productserve.com/preview/736/88966064.jpg
[mLink] => http://www.cadburygiftsdirect.co.uk/products/608-50-off-56g-creme-egg-minis.aspx
[mImage] => http://www.cadburygiftsdirect.co.uk/images/thumbs/0001084.png
)
[price] => Array
(
[XML_Serializer_Tag] => Array
(
[curr] => GBP
)
[buynow] => 0.31
[store] => 0.00
[rrp] => 0.00
[delivery] => 0.00
)
[cat] => Array
(
[awCatId] => 437
[awCat] => Chocolate
[mCat] => Full Range
)
[brand] =>
[valFrom] => 0000-00-00
[valTo] => 0000-00-00
[comAmount] => 0.00
)
The segment loop afterwards.
So...
[1] => Array
[2] => Array
[3] => Array
etc...
I need to find the names of the attributes of each array segment.
So I have used this recursive loop:
private function recursive_array($old_array, $new_array = array()) {
foreach ($old_array as $key => $value) {
if (is_array($value) && $key < 1) {
$new_array = $this->recursive_array($value, $new_array);
} else {
if ($key < 1) {
$new_array[] = $key;
}
}
}
return $new_array;
}
This is the output:
array
0 => string 'id' (length=2)
1 => string 'name' (length=4)
2 => string 'id' (length=2)
3 => string 'pre_order' (length=9)
4 => string 'web_offer' (length=9)
5 => string 'in_stock' (length=8)
6 => string 'stock_quantity' (length=14)
7 => string 'pId' (length=3)
8 => string 'isbn' (length=4)
9 => string 'name' (length=4)
10 => string 'desc' (length=4)
11 => string 'awTrack' (length=7)
12 => string 'awThumb' (length=7)
13 => string 'awImage' (length=7)
14 => string 'mLink' (length=5)
15 => string 'mImage' (length=6)
16 => string 'curr' (length=4)
17 => string 'buynow' (length=6)
18 => string 'store' (length=5)
19 => string 'rrp' (length=3)
20 => string 'delivery' (length=8)
21 => string 'awCatId' (length=7)
22 => string 'awCat' (length=5)
23 => string 'mCat' (length=4)
24 => string 'brand' (length=5)
25 => string 'valFrom' (length=7)
26 => string 'valTo' (length=5)
27 => string 'comAmount' (length=9
What it is also picking up is the top nested array:
[XML_Serializer_Tag] => Array
(
[id] => 736
[name] => Cadbury Gifts Direct
)
This is just details for the entire feed not the individual segments.
I need a way of filtering out the top nested array but bear in mind that the details are dynamic so the name of the keys can change from one feed to the next

Maybe this?
$riter = new RecursiveIteratorIterator(New RecursiveArrayIterator($array));
foreach ($riter as $key => $val) {
if ($riter->getDepth() > 1) {
echo "$key => $val\n";
}
}
by default, RecursiveIteratorIterator only visits leaf nodes(the deepest levels down every path). getDepth() can be used to make sure were a minimum depth. I'm not sure if 1 is the correct number, but anyway...

use array_shift to pop off the first element of the array

Related

How to parse this format?

I'm trying to parse a string which looks like this :
"['x','y','z',['a'],[],[['name','2'],['name','40']]]"
I would like to put everythings in an array like this :
0 => string 'x' (length=1)
1 => string 'y' (length=1)
2 => string 'z' (length=1)
3 =>
array (size=1)
0 => string 'a' (length=1)
4 =>
array (size=0)
empty
5 =>
array (size=2)
0 =>
array (size=2)
0 => string 'name' (length=4)
1 => string '2' (length=1)
1 =>
array (size=2)
0 => string 'name' (length=4)
1 => string '40' (length=2)
Is there a proper way to do it because I tried to make a bunch of functions, but at the end it's always a mess and it doesn't work.
Thats nearly a JSON String, so make it into one and from there its easy running
$nearlyJson = "['x','y','z',['a'],[],[['name','2'],['name','40']]]";
$nowItsJson = str_replace("'", '"', $nearlyJson );
$NowItsAPHPArray = json_decode($nowItsJson );
print_r($NowItsAPHPArray );
RESULT
Array
(
[0] => x
[1] => y
[2] => z
[3] => Array
(
[0] => a
)
[4] => Array
(
)
[5] => Array
(
[0] => Array
(
[0] => name
[1] => 2
)
[1] => Array
(
[0] => name
[1] => 40
)
)
)

array_sum() to values within an array

How can i add array_sum to the string in my loop without making another foreach loop for it? I am trying to combine all of the numbers together instead of having this multi dimensional array and then just have the value and i see that array_sum wont add them up because its inside of an array. any ideas?
$hours_arr = array();
foreach($proj_time as $item){
$hours_arr [$item['project_id']]['item_value'] = $item['item_value'];
$hours_arr [$item['project_id']]['hours'][] = $item['hours'];
}
//output
array (size=3)
4 =>
array (size=2)
'item_value' => string 'Coaching' (length=8)
'hours' =>
array (size=1)
0 => string '999.99' (length=6)
1487 =>
array (size=2)
'item_value' => string 'Standby' (length=7)
'hours' =>
array (size=1)
0 => string '15.00' (length=5)
1488 =>
array (size=2)
'item_value' => string 'Standby' (length=7)
'hours' =>
array (size=4)
0 => string '10.00' (length=5)
1 => string '10.00' (length=5)
2 => string '10.00' (length=5)
3 => string '10.00' (length=5)
I would like my output to be
1488 =>
array (size=2)
'item_value' => string 'Standby' (length=7)
'hours' => string '40.00' (length=5)
edit: added contents of $proj_time
Array
(
[0] => Array
(
[project_id] => 4
[consultant_id] => 51
[engagement_id] => 8
[hours] => 999.99
[item_value] => Coaching
)
[1] => Array
(
[project_id] => 1487
[consultant_id] => 1
[engagement_id] => 1
[hours] => 15.00
[item_value] => Standby
)
[2] => Array
(
[project_id] => 1488
[consultant_id] => 31
[engagement_id] => 7
[hours] => 10.00
[item_value] => Design App RFP
)
[3] => Array
(
[project_id] => 1488
[consultant_id] => 32
[engagement_id] => 41
[hours] => 10.00
[item_value] => Training
)
[4] => Array
(
[project_id] => 1488
[consultant_id] => 55
[engagement_id] => 41
[hours] => 10.00
[item_value] => Training
)
[5] => Array
(
[project_id] => 1488
[consultant_id] => 1
[engagement_id] => 1
[hours] => 10.00
[item_value] => Standby
)
)
Instead of creating array and then applying operation, while creating itself why don't you sum up like this:
DEMO
$hours_arr = array();
foreach($proj_time as $item){
$hours_arr [$item['project_id']]['item_value'] = $item['item_value'];
if(array_key_exists('hours', $hours_arr [$item['project_id']]))
$hours_arr [$item['project_id']]['hours'] += $item['hours'];
else
$hours_arr [$item['project_id']]['hours'] = $item['hours'];
}
Result:
Array
(
[4] => Array
(
[item_value] => Coaching
[hours] => 999.99
)
[1487] => Array
(
[item_value] => Standby
[hours] => 15
)
[1488] => Array
(
[item_value] => Standby
[hours] => 40
)
)
Try this out
<?php
$hours_arr = array();
foreach($proj_time as $item){
if(!isset($hours_arr [$item['project_id']]) || $hours_arr [$item['project_id']]['item_value'] != $item['item_value']) {
$hours_arr [$item['project_id']]['item_value'] = $item['item_value'];
$hours_arr [$item['project_id']]['hours'][] = $item['hours'];
} else {
$hours_arr [$item['project_id']]['hours'][0] += $item['hours'];
}
}

php array count same key after merge to separate comma

I using codeigniter 3.x version.
This is value passed to the ajax.
Array (
[0] => 10:4
[1] => 11:1
[2] => 12:2
[3] => 13:3
[4] => 14:4
[5] => 15:5
[6] => 16:4
[7] => 17:3
[8] => 18:2
[9] => 19:1
[10] => 1:4 // duplicate
[11] => 1:5 // duplicate
[12] => 20:2
[13] => 21:3
[14] => 22:4
[15] => 23:5
[16] => 24:4 // duplicate
[17] => 24:5 // duplicate
[18] => 25:2
[19] => 2:5
[20] => 3:4
[21] => 4:4
[22] => 5:4
[23] => 6:3
[24] => 7:2
[25] => 8:3
[26] => 9:2 // duplicate
[27] => 9:4 // duplicate
)
I want to insert into the database, Processing the array
First, sort to use natsort($data)
1:4
1:5
2:5
3:4
4:4
5:4
6:3
7:2
8:3
9:2
10:4
11:1
12:2
13:3
14:4
15:5
16:4
17:3
18:2
19:1
20:2
21:3
22:4
23:5
24:4
24:5
25:2
25:5
It was satisfactory.
but
1:4
1:5
24:4
24:5
25:2
25:5
is has duplicate value
My questions is
1:4
1:5
24:4
24:5
25:2
25:5
to
1:4,5
2:5
3:4
.
.
24:4,5
25:2,5
How should this be handled on php?
This might help -
$new= [];
foreach($ar as $v) {
$temp = explode(':', $v);
$new[$temp[0]][] = $temp[1];
}
foreach($new as $k => $v) {
$new[$k] = $k . ':' . implode(',', $v);
}
DEMO
$keys = array();
$list = array(
'1:4','1:5','2:1','3:4','4:1','4:2'
);
// Seach the keys
foreach($list as $item){
$key = substr($item,0,strpos($item, ':'));
$val = substr($item,strpos($item, ':')+1);
if(!isset($keys[$key])) $keys[$key] = array();
$keys[$key][] = $val;
}
//And now you can handle how do you want
$final = array();
foreach($keys as $key => $value){
$final[$key] = implode(',',$value);
}
var_dump($list);
var_dump($keys);
var_dump($final);
===================== OUTPUT =====================
$list:
array (size=6)
0 => string '1:4' (length=3)
1 => string '1:5' (length=3)
2 => string '2:1' (length=3)
3 => string '3:4' (length=3)
4 => string '4:1' (length=3)
5 => string '4:2' (length=3)
$keys:
array (size=4)
1 =>
array (size=2)
0 => string '4' (length=1)
1 => string '5' (length=1)
2 =>
array (size=1)
0 => string '1' (length=1)
3 =>
array (size=1)
0 => string '4' (length=1)
4 =>
array (size=2)
0 => string '1' (length=1)
1 => string '2' (length=1)
$final:
array (size=4)
1 => string '4,5' (length=3)
2 => string '1' (length=1)
3 => string '4' (length=1)
4 => string '1,2' (length=3)
You can achieve it in two step ..
Get all first part and set values to all duplicates by making it key
Reverse engineering to achieve result
$a=array('1:4' ,'1:5' ,'24:4','24:5','25:2','25:5');//input here
$temp=array();
$result=array();
foreach($a as $v)
{
$part=explode(":",$v);
if(isset($temp[$part[0]]))
$temp[$part[0]].=",".$part[1];
else
$temp[$part[0]]=$part[1];
}
foreach($temp as $k=>$v)
{
$result[]=$k.":".$v;
}
print_r($result);
OUPTUT
Array ( [0] => 1:4,5 [1] => 24:4,5 [2] => 25:2,5 )

Sort php different format multidimensional array on key

I have an array like this
Array
(
[name] => Array
(
[0] => img/test240.jpg
[1] => img/cs1.jpg
[2] => img/cs2.jpg
[3] => img/cs3.jpg
)
[link] => Array
(
[0] => http://google.com
[1] => http://google.com
[2] => http://facebook.com
[3] => http://orkut.com
)
[order] => Array
(
[0] => 4
[1] => 1
[2] => 2
[3] => 3
)
)
I need to sort it by order WHICH IS KEY in Multidimensional array. Here is output.
Array
(
[name] => Array
(
[1] => img/cs1.jpg
[2] => img/cs2.jpg
[3] => img/cs3.jpg
[0] => img/test240.jpg
)
[link] => Array
(
[1] => http://google.com
[2] => http://facebook.com
[3] => http://orkut.com
[0] => http://google.com
)
[order] => Array
(
[1] => 1
[2] => 2
[3] => 3
[0] => 4
)
)
In this you can see when order is sorted name and link is also sorted according to the order. How can i do this with php.
You have to use array_map() in conjunction with sort().
If you want to preserve actual element order you have to use asort() instead sort().
Try this code:
$arr = array(
'name' => array(
0 => 'img/test240.jpg',
1 => 'img/cs1.jpg',
2 => 'img/cs2.jpg',
3 => 'img/cs3.jpg',
),
'link' => array(
0 => 'http://google.com',
1 => 'http://google.com',
2 => 'http://facebook.com',
3 => 'http://orkut.com',
),
'order' => array(
0 => 4,
1 => 1,
2 => 2,
3 => 3,
),
);
function mysort($a) {
asort($a);
return $a;
}
$arr = array_map('mysort', $arr);
print_r($arr);
Demo.
Try this, it uses array_multisort:
$array holds:
array (size=3)
'name' =>
array (size=4)
0 => string 'img/test240.jpg' (length=15)
1 => string 'img/cs1.jpg' (length=11)
2 => string 'img/cs2.jpg' (length=11)
3 => string 'img/cs3.jpg' (length=11)
'link' =>
array (size=4)
0 => string 'http://google.com' (length=17)
1 => string 'http://google.com' (length=17)
2 => string 'http://facebook.com' (length=19)
3 => string 'http://orkut.com' (length=16)
'order' =>
array (size=4)
0 => string '4' (length=1)
1 => string '1' (length=1)
2 => string '2' (length=1)
3 => string '3' (length=1)
Code:
$sort = array();
foreach($array as $k) {
foreach($k as $ind=>$val){
$sort['name'][$ind] = $array['name'][$ind];
$sort['link'][$ind] = $array['link'][$ind];
$sort['order'][$ind] = $array['order'][$ind];
}
}
array_multisort($sort['order'], SORT_ASC, $sort['link'], SORT_ASC, $sort['name'], SORT_ASC);
var_dump($sort);
Output:
array (size=3)
'name' =>
array (size=4)
0 => string 'img/cs1.jpg' (length=11)
1 => string 'img/cs2.jpg' (length=11)
2 => string 'img/cs3.jpg' (length=11)
3 => string 'img/test240.jpg' (length=15)
'link' =>
array (size=4)
0 => string 'http://google.com' (length=17)
1 => string 'http://facebook.com' (length=19)
2 => string 'http://orkut.com' (length=16)
3 => string 'http://google.com' (length=17)
'order' =>
array (size=4)
0 => string '1' (length=1)
1 => string '2' (length=1)
2 => string '3' (length=1)
3 => string '4' (length=1)
$this_arr = array(1,2,3,0);
function my_sort_2($arr, $arrangement)
{
$flag = false;
foreach($arr as $key => $val)
{
if(is_array($arr[$key]))
{
$arr[$key] = my_sort_2($arr[$key],$arrangement);
$flag = true;
}
}
if($flag == false && is_array($arr) && is_assoc($arr) === false)
{
$temp = array();
for($i = 0; $i < count($arrangement); $i++)
{
if(isset($arr[$arrangement[$i]]))
{
$temp[$arrangement[$i]] = $arr[$arrangement[$i]];
unset($arr[$arrangement[$i]]);
}
}
//$arr = array_merge($temp,$arr);
$arr = $temp;
}
return $arr;
}
Include this function below to run my own function. Also credit to #Matt Whittingham where i got this code from
function is_assoc($array)
{
$keys = array_keys($array);
return array_keys($keys) !== $keys;
}
Now let's do some sortin'... print_r(my_sort_2($arr,$this_arr)); assuming $arr contains Shan's array.
The output is EXACTLY what you desired.
It'll search for nested array (at least intended) and see if it's in a standard numeric ordered keys (in short, not custom order - yet; and not assoc) then sort it the way you want.
Note: I know my code isn't that probably good, optimized or bug free and that's my second attempt, misunderstanding your requirements first time (see the function name?).
Well after some research i found a simple solution like this
asort($data['order']);
$keys = array_keys($data['order']);
$data['name'] = array_replace(array_flip($keys), $data['name']);
$data['link'] = array_replace(array_flip($keys), $data['link']);
$data['order'] = array_replace(array_flip($keys), $data['order']);
Although i dont want to apply array_replace and array_flip on all the keys but this is done for the time being. I will surely trying to find how i can do it with single instruction.

How can I loop through this array - PHP

This is the var_dump($options)
array (size=4)
0 => string '2' (length=1)
'parent_2_children' =>
array (size=3)
0 => string '22' (length=2)
1 => string '24' (length=2)
2 => string '23' (length=2)
1 => string '3' (length=1)
'parent_3_children' =>
array (size=3)
0 => string '26' (length=2)
1 => string '25' (length=2)
2 => string '27' (length=2)
What I have tried up to now is
if(!is_null($options))
{
foreach($options as $option)
{
if(!array_key_exists('parent_'.$option.'_children',$options))
{
//if position null output an error
}
}
}
Print_r() as requested
Array
(
[0] => 2
[parent_2_children] => Array
(
[0] => 22
[1] => 24
[2] => 23
)
[1] => 3
[parent_3_children] => Array
(
[0] => 26
[1] => 25
[2] => 27
)
)
use print_r($options) in staid of var_dump it's easier to read..
check if you got a numeric key, then check if the new key exists. Throw an error.
if(!is_null($options)) {
foreach($options as $key => $option) {
if(is_int($key) && !array_key_exists('parent_'.$option.'_children',$options)) {
echo 'parent_'.$option.'_children does not exist';
}
}
}
Here is a working example
Your code is correct. An additional check on the nature of the key will reduce the execution, since you have to do the processing only for numeric keys.
if(!is_null($options))
{
foreach($options as $key => $option)
{
if (is_numeric($key)) {
if(!array_key_exists('parent_'.$option.'_children',$options))
{
print 'parent_'.$option.'_children does not exist';
}
}
}
}
To test the code, try the following array :
$options = array(0 => 2, 'parent_2_children' => array ( 0 => 22, 1 => 24, 2 => 23 ), 1 => 3, 'parent_3_children' => array ( 0 => 26, 1 => 25, 2 => 27 ), 2=>4 );
whose print_r output will be :
Array
(
[0] => 2
[parent_2_children] => Array
(
[0] => 22
[1] => 24
[2] => 23
)
[1] => 3
[parent_3_children] => Array
(
[0] => 26
[1] => 25
[2] => 27
)
[2] => 4
)
and, it will output :
parent_4_children does not exist
Try this?
if(!is_null($options)){
foreach($options as $option){
if(!array_key_exists('parent_'.$option.'_children',$options)){
throw new Exception("Something went wrong!");
}
}
}

Categories