Convert multi-dimensional array key value - php

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...

Related

array_multisort issue with multidimensonal array in PHP

I have the following array:
array(10) {
[0]=> array(109) {
["id"]=> string(4) "2632", ["_category_sortorder"] => 8, ["_sortorder" => 1]
},
[1]=> array(109) {
["id"]=> string(4) "2635", ["_category_sortorder"] => 5, ["_sortorder" => 2]
},
...
}
I want to sort it based on two criterias:
a) by _category_sortorder asc (with priority)
b) by _sortorder asc
I tried this:
foreach($resources as $k => $v) {
$sort[$k]['_category_sortorder'] = $resources[$k]['_category_sortorder'];
$sort[$k]['_sortorder'] = $resources[$k]['_sortorder'];
}
array_multisort($sort['_category_sortorder'], SORT_ASC, $sort['_sortorder'], SORT_ASC, $resources);
But it's not working as expected. Any suggestions?
Try like this,
$sort = array(
array("id"=>"263", "_category_sortorder"=> 8, "_sortorder" => 1),
array( "id"=> "145", "_category_sortorder" => 155, "_sortorder" => 2),
array( "id"=> "2145", "_category_sortorder" => 55, "_sortorder" => 12),
array( "id"=> "3145", "_category_sortorder" => 155, "_sortorder" => 10),
);
usort($sort, function(array $a, array $b) {
return $b['_category_sortorder'] - $a['_category_sortorder'];
});
echo '<pre>';
print_r($sort);
echo '</pre>';
I think there is a simple solution but this code block is doing is job:
You split the array in sub arrays including only elements with the same _category_sortorder value. Then you sort each sub array with usort. At the end you merge them together.
<?php
$array = [
['id' => 1, '_category_sortorder' => 2, '_sortorder' => 1],
['id' => 2, '_category_sortorder' => 2, '_sortorder' => 3],
['id' => 3, '_category_sortorder' => 3, '_sortorder' => 19],
['id' => 4, '_category_sortorder' => 1, '_sortorder' => 2],
['id' => 5, '_category_sortorder' => 1, '_sortorder' => 1],
];
foreach ($array as $value) {
if (!isset($newElements[$value['_category_sortorder']]))
$newElements[$value['_category_sortorder']] = [];
$newElements[$value['_category_sortorder']][] = $value;
}
$array = [];
foreach ($newElements as $key => $value) {
usort($value, function($a, $b) {
return strcmp($a["_sortorder"], $b["_sortorder"]);
});
$array[$key] = $value;
}
ksort($array);
$new = [];
foreach ($array as $value) {
$new = array_merge($new, $value);
}
echo "<pre>".print_r($new, true).'</pre>';

PHP extract Multidimensional Associative Array Keys as Text

With a basic associative array like:
$ar = array("First" => 1, "Second" , "Third" =>"Three");
if you do:
foreach($ar as $key => $val) {
var_dump($key);
}
This will produce:
string 'First' (length=5)
int 0
string 'Third' (length=5)
How do you Achieve the same results in a Multidimensional Array?
Something like:
array( 0 => array(
"First" => 1, "Two", "Third" => "Three"
)
);
I tried:
foreach($ar as $k => $v){
var_dump($ar[0][$k]);
}
I got:
string 'Two' (length=3)
Instead of:
string 'First' (length=5)
int 0
string 'Third' (length=5)
Thanx
function get_key(&$arr){
foreach($arr as $key=>$value){
if(is_array($value)){
get_key($value);
}else{
var_dump($key);
}
}
}
$arr = array(
'key1'=>array('a'=>1,'b'=>2),
'key2'=>array('c'=>1,2),
);
get_key($arr);
output:
string(1) "a"
string(1) "b"
string(1) "c"
int(0)
If $ar is equal to this:
array( 0 => array(
"First" => 1, "Two", "Third" => "Three"
)
);
You could iterate over the inner array to get the same result:
foreach ($ar as $k => $v) {
foreach ($v as $k2 => $v2) {
var_dump($k2);
}
}
Output:
string(5) "First"
int(0)
string(5) "Third"
You can iterate through the values of the inner array like this:
foreach($ar[0] as $k => $v){
var_dump($v);
}
The problem with yours is that you are only looping over 1 element in the ar array, and then applying that number to the array inside of it.
If you also want to do the same thing on both levels, you need another foreach loop like so:
foreach($ar as $k => $v){
foreach($v as $k => $n){
var_dump($n);
}
}
$arr = array(
0 => array("First" => 1, "Two", "Third" => "Three")
);
foreach ($arr as $key => $value)
{
foreach ($value as $k => $v)
{
var_dump($k);
}
}
You can access multidimensional Array keys and indexes like so:
$ary = array('whatever' => array('First' => 1, 'Two', 'Third' => 'Three'),
array('something' => array('cool' => 'yes', 'awesome' => 'super', 'great' => 10)
);
foreach($ary as $k => $a){
// $k is each Array key within initial Array
foreach($a as $i => $v){
// $i is internal index
// $v is internal value
}
}
Note:
In an Array that contains Arrays the first Array is really the value under key 0, unless the Array is assigned to a key, so your key, 0, is not necessary.

How to extract and remove selected variables from an array?

I have the following array:
$var_array = array(
"length" => 5,
"breadth" => 5,
"color" => "blue",
"size" => "medium",
"shape" => "square");
How do I extract selected variables out of the array by specifying the keys?
Example if I specify breadth and size, I get:
$breadth = 5;
$size = "medium";
$var_array = array(
"length" => 5,
"color" => "blue",
"shape" => "square");
array_diff_key and array_intersect_key:
$array = array(
'breadth' => 1,
'size' => 2,
'length' => 3,
'colour' => 4,
'shape' => 5
);
$keys = array('breadth', 'size');
$new_array = array_intersect_key($array, array_flip($keys));
$array = array_diff_key($array, $new_array);
Will produce:
// $new_array
array(2) {
["breadth"] => int(1)
["size"] => int(2)
}
// $array
array(3) {
["length"] => int(3)
["colour"] => int(4)
["shape"] => int(5)
}
If you want to put them into local variables you can do:
list($length, $colour, $shape) = array_values($new_array);
Or a less clear version:
extract($new_array);
Solution:
$keys = array('breadth', 'size'); // which keys do you want to extract?
foreach($keys as $key) {
$newArr[$key] = $var_array[$key]; // put'em in newArr
unset($var_array[$key]);
}
extract($newArr); // extract them to convert keys to variables
unset($newArr); // unset newArr
goldenparrot has already provided a good answer, but in case you want a solution that doesn't use foreach, you could use array_intersect_key instead:
$var_array = array(...)
$keysToExtract = array('breadth', 'size');
extract(array_intersect_key($var_array, array_fill_keys($keysToExtract, true));
Try this
$var_array = array(
"length" => 5,
"breadth" => 5,
"color" => "blue",
"size" => "medium",
"shape" => "square");
reset($var_array);
$myarray =array();
while (list($key, $val) = each($var_array))
{
if($key!='length' && $key!='size' )
{
$myarray[$key] = $val;
}else{
echo "$key => $val<br />";
}
}
output
size=> medium
breadth => 5
Array
(
[color] => blue
[length] => 5
[shape] => square
)

PHP Sum up values in 2-Dimensional array that have same key value

Problem: Find the sum of the values in 'subtotal' for each 'id' and store the respective sum for each id in an array (or variables).
My sloppy solution at the moment is to run a foreach with multiple if statements inside that count the occurrences. This is adequate for something like 5 ids, but I have to iterate this over 38 ids.
I would like to store the results sequentially in an array if possible.
How can I make it more efficient? Any and all help will be appreciated.
(See my sloppy solution at the end of this for a good chuckle)
Desired Result:
sum of all ID 1 = 10
sum of all ID 2 = 18
sum of all ID 3 = 14
sum of all ID 4 = 4
sum of all ID 5 = 3
Array Code for Manipulation
$someArray = array(
array(
'id'=> 1,
'subtotal'=> 5),
array(
'id'=> 1,
'subtotal'=> 5),
array(
'id'=> 2,
'subtotal'=> 6),
array(
'id'=> 2,
'subtotal'=> 6),
array(
'id'=> 2,
'subtotal'=> 6),
array(
'id'=> 3,
'subtotal'=> 7),
array(
'id'=> 3,
'subtotal'=> 7),
array(
'id'=> 4,
'subtotal'=> 2),
array(
'id'=> 4,
'subtotal'=> 2),
array(
'id'=> 5,
'subtotal'=> 3),
);
Sloppy Solution
$sum_id_1 = 0;
$sum_id_2 = 0;
$sum_id_3 = 0;
$sum_id_4 = 0;
$sum_id_5 = 0;
foreach ($someArray as $k) {
if ($k['id'] == 1) {
$sum_id_1 += $k['subtotal'];
}
if ($k['id'] == 2) {
$sum_id_2 += $k['subtotal'];
}
if ($k['id'] == 3) {
$sum_id_3 += $k['subtotal'];
}
if ($k['id'] == 4) {
$sum_id_4 += $k['subtotal'];
}
if ($k['id'] == 5) {
$sum_id_5 += $k['subtotal'];
}
}
Sloppy Solution Output (on echo)
10
18
14
4
3
$sum = array_reduce($someArray, function($result, $item) {
if (!isset($result[$item['id']])) $result[$item['id']] = 0;
$result[$item['id']] += $item['subtotal'];
return $result;
}, array());
var_dump($sum); // array(5) { [1]=> int(10) [2]=> int(18) [3]=> int(14) [4]=> int(4) [5]=> int(3) }
For PHP <= 5.3 perform the counting in loop manually:
$sum = array();
foreach ($someArray as $item) {
if (!isset($sum[$item['id']])) $sum[$item['id']] = 0;
$sum[$item['id']] += $item['subtotal'];
}
$arr3 = array (
"0" => array ( "001" => 10 ),
"1" => array ( "005" => 20 ),
"2" => array ( "001" => 30 ),
"3" => array ( "003" => 20 ),
"4" => array ( "005" => 80 ),
"5" => array ( "001" => 90 ),
"6" => array ( "003" => 20 ),
"7" => array ( "006" => 80 ),
"8" => array ( "006" => 90 )
) ;
array (size=4)
0 =>
array (size=1)
'001' => int 130
1 =>
array (size=1)
'005' => int 100
2 =>
array (size=1)
'003' => int 40
3 =>
array (size=1)
'006' => int 170
$outer_array = array();
$unique_array = array();
$inner_array = array();
foreach($arr3 as $key => $value)
{
$item = key($value);
if(!in_array(key($value), $unique_array))
{
array_push($unique_array, $item);
$inner_array[key($value)] = $value[$item];
$outer_array[$item][$item] = $value[$item];
}else{
$inner_array[key($value)] = $value[$item] + $inner_array[$item];
$outer_array[$item][$item] = $inner_array[$item];
}
}
var_dump(array_values($outer_array));
if you want to sum up all the values with the same key.namely, the above result is what you hope.so my answer is approaching……that is all, wish will help somebody encountering the same situation about this question!

Moving array element to top in PHP

$arr = array(
'a1'=>'1',
'a2'=>'2'
);
I need to move the a2 to the top, as well as keep the a2 as a key how would I go on about it I can't seem to think a way without messing something up :)
Here is a solution which works correctly both with numeric and string keys:
function move_to_top(&$array, $key) {
$temp = array($key => $array[$key]);
unset($array[$key]);
$array = $temp + $array;
}
It works because arrays in PHP are ordered maps.
Btw, to move an item to bottom use:
function move_to_bottom(&$array, $key) {
$value = $array[$key];
unset($array[$key]);
$array[$key] = $value;
}
You can achieve that this way:
$arr = array(
'a1'=>'1',
'a2'=>'2'
);
end($arr);
$last_key = key($arr);
$last_value = array_pop($arr);
$arr = array_merge(array($last_key => $last_value), $arr);
/*
print_r($arr);
will output (this is tested):
Array ( [a2] => 2 [a1] => 1 )
*/
try this:
$key = 'a3';
$arr = [
'a1' => '1',
'a2' => '2',
'a3' => '3',
'a4' => '4',
'a5' => '5',
'a6' => '6'
];
if (isset($arr[ $key ]))
$arr = [ $key => $arr[ $key ] ] + $arr;
result:
array(
'a3' => '3',
'a1' => '1',
'a2' => '2',
'a4' => '4',
'a5' => '5',
'a6' => '6'
)
Here's a simple one liner to get this done with array_splice() and the union operator:
$arr = array('a1'=>'1', 'a2'=>'2', 'a3' => '3');
$arr = array_splice($arr,array_search('a2',array_keys($arr)),1) + $arr;
Edit:
In retrospect I'm not sure why I wouldn't just do this:
$arr = array('a2' => $arr['a2']) + $arr;
Cleaner, easier and probably faster.
You can also look at array_multisort This lets you use one array to sort another. This could, for example, allow you to externalize a hard-coded ordering of values into a config file.
<?php
$ar1 = array(10, 100, 100, 0);
$ar2 = array(1, 3, 2, 4);
array_multisort($ar1, $ar2);
var_dump($ar1);
var_dump($ar2);
?>
In this example, after sorting, the first array will contain 0, 10, 100, 100. The second array will contain 4, 1, 2, 3. The entries in the second array corresponding to the identical entries in the first array (100 and 100) were sorted as well.
Outputs:
array(4) {
[0]=> int(0)
[1]=> int(10)
[2]=> int(100)
[3]=> int(100)
}
array(4) {
[0]=> int(4)
[1]=> int(1)
[2]=> int(2)
[3]=> int(3)
}

Categories