How to sort multidimensional array in PHP - php

I have tried almost all suggestions online, and I really can't figure out how to sort this SESSION array.
I want it sorted by "itemname"..
I have and want this output, but I need the itemname to determine which item array come first.
Array
(
[person] => Array
(
[namex] => Array
(
[itema] => Array
(
[itemid] => 43
[itemname] => def
)
[itemc] => Array
(
[itemid] => 33
[itemname] => abc
)
[itemg] => Array
(
[itemid] => 29
[itemname] => ghi
)
)
[namey] => Array
(
[itemj] => Array
(
[itemid] => 12
[itemname] => abc
)
[iteme] => Array
(
[itemid] => 44
[itemname] => jkl
)
[itemr] => Array
(
[itemid] => 20
[itemname] => rst
)
)
)
)
So, "person" stays the same, but name, item, itemid and itemname is always different.
Can anyone help me sort this by itemname?
I need the array to be like this, so can't change it up.
Also.. I need to access it later in a foreach, so I can print out the items.

As pointed out in the comments to the question the desired output is not really defined. You'd have to give a specific definition of the output, without that we have to assume what you probably are looking for:
<?php
$data = [
"person" => [
"namex" => [
"itema" => [
"itemid" => 43,
"itemname" => "def"
],
"itemc" => [
"itemid" => 33,
"itemname" => "abc"
],
"itemg" => [
"itemid" => 29,
"itemname" => "ghi"
]
],
"namey" => [
"itemj" => [
"itemid" => 12,
"itemname" => "abc"
],
"iteme" => [
"itemid" => 44,
"itemname" => "jkl"
],
"itemr" => [
"itemid" => 20,
"itemname" => "rst"
]
]
]
];
foreach ($data["person"] as $personName => &$person) {
uasort($person, function($a, $b) {
return $a["itemname"] > $b["itemname"];
});
}
print_r($data);
The obvious output is:
Array
(
[person] => Array
(
[namex] => Array
(
[itemc] => Array
(
[itemid] => 33
[itemname] => abc
)
[itema] => Array
(
[itemid] => 43
[itemname] => def
)
[itemg] => Array
(
[itemid] => 29
[itemname] => ghi
)
)
[namey] => Array
(
[itemj] => Array
(
[itemid] => 12
[itemname] => abc
)
[iteme] => Array
(
[itemid] => 44
[itemname] => jkl
)
[itemr] => Array
(
[itemid] => 20
[itemname] => rst
)
)
)
)

Assuming the input from the example is represented via array as:
<?php
$array = [
'person' => [
'namex' => [
'itema' => [
'itemid' => 43,
'itemname' => 'def'
],
'itemb' => [
'itemid' => 33,
'itemname' => 'abc'
],
'itemc' => [
'itemid' => 29,
'itemname' => 'ghi'
],
],
'namey' => [
'itema' => [
'itemid' => 12,
'itemname' => 'abc'
],
'itemb' => [
'itemid' => 44,
'itemname' => 'jkl'
],
'itemc' => [
'itemid' => 20,
'itemname' => 'rst'
],
],
]
];
You could do use array_multisort in a loop:
$ids = [];
foreach($array as $key => $value) {
foreach ($value as $newKey => $value2) {
$ids[$newKey] = array_column($value2, 'itemname');
array_multisort($ids[$newKey], SORT_NATURAL, $array[$key][$newKey]);
}
}
This will output
array(1) {
'person' =>
array(2) {
'namex' =>
array(3) {
'itemb' =>
array(2) {
'itemid' =>
int(33)
'itemname' =>
string(3) "abc"
}
'itema' =>
array(2) {
'itemid' =>
int(43)
'itemname' =>
string(3) "def"
}
'itemc' =>
array(2) {
'itemid' =>
int(29)
'itemname' =>
string(3) "ghi"
}
}
'namey' =>
array(3) {
'itema' =>
array(2) {
'itemid' =>
int(12)
'itemname' =>
string(3) "abc"
}
'itemb' =>
array(2) {
'itemid' =>
int(44)
'itemname' =>
string(3) "jkl"
}
'itemc' =>
array(2) {
'itemid' =>
int(20)
'itemname' =>
string(3) "rst"
}
}
}
}

Related

How to merge array on behalf of a key value

I have an array
{
Array
(
[0] => Array
(
[filterType] => checkbox
[sfid] => a1d1I000000jrmwQAA
[name] => Publication Year
[specValues] => Array
(
[count] => 3
[value] => 1953
)
)
[1] => Array
(
[filterType] => checkbox
[sfid] => a1d1I000000jrmwQAA
[name] => Publication Year
[specValues] => Array
(
[count] => 1
[value] => 1954
)
)
)
}
But I want to merge array if sfid is same i.e i want result
{
Array
(
[0] => Array
(
[filterType] => checkbox
[sfid] => a1d1I000000jrmwQAA
[name] => Publication Year
[specValues] => Array(
[0] =>array(
[count] => 3
[value] => 1953
)
[1] =>array(
[count] => 1
[value] => 1954
)
)
)
)
}
You just need to iterate your array and add the row to the output if it is not in there already (you can use sfid as keys) and add specValues to the correct row.
<?php
$input = [
[
'filterType' => 'checkbox',
'sfid' => 'a1d1I000000jrmwQAA',
'name' => 'Publication Year',
'specValues' => [
'count' => 3,
'value' => 1953,
],
],
[
'filterType' => 'checkbox',
'sfid' => 'a1d1I000000jrmwQAA',
'name' => 'Publication Year',
'specValues' => [
'count' => 1,
'value' => 1954,
],
],
];
$data = [];
foreach ($input as $row) {
if (!isset($data[$row['sfid']])) {
$data[$row['sfid']] = [
'filterType' => $row['filterType'],
'sfid' => $row['sfid'],
'name' => $row['name'],
'specValues' => [],
];
}
$data[$row['sfid']]['specValues'][] = $row['specValues'];
}
var_dump(array_values($data));
Output:
array(1) {
[0]=>
array(4) {
["filterType"]=>
string(8) "checkbox"
["sfid"]=>
string(18) "a1d1I000000jrmwQAA"
["name"]=>
string(16) "Publication Year"
["specValues"]=>
array(2) {
[0]=>
array(2) {
["count"]=>
int(3)
["value"]=>
int(1953)
}
[1]=>
array(2) {
["count"]=>
int(1)
["value"]=>
int(1954)
}
}
}
}
I assume that if sfid is the same, then also filterType and name is the same.

How to create tree view hierarchy in php codeigniter?

I have a array like this :
Array
(
[0] => Array
(
[id] => 1
[child_name] => "Emma"
[parent_name] => "Mr Brown"
)
[1] => Array
(
[id] => 2
[child_name] => "John"
[parent_name] => "Mr Brown"
)
[2] => Array
(
[id] => 3
[child_name] => "Joseph"
[parent_name] => "Mr Thomas"
)
[3] => Array
(
[id] => 4
[child_name] => "Pretty"
[parent_name] => "Mr Thomas"
)
[4] => Array
(
[id] => 5
[child_name] => "Raphel"
[parent_name] => "Mr Brown"
)
[5] => Array
(
[id] => 6
[child_name] => "Tommy"
[parent_name] => "Mr Thomas"
)
[6] => Array
(
[id] => 7
[child_name] => "Tim"
[parent_name] => "Mr Thomas"
)
)
From this array I want to generate a view like this :
The parent_name field becomes the MainCategory and the child_name becomes the subcategory. The names have checkboxes in front of them.
How do I achieve this? I don't have much experience in php. I code in node js but this task needs this to be done in php.
How do I do this?
Try this, Here i use simple index() method and pass data to view file as an example.
You can use below code and test in your codeigniter.
Hope this will work for you.
Welcome.php (Controller)
public function index()
{
$array = [
[
'id' => 1,
'child_name' => "Emma",
'parent_name' => "Mr Brown",
],
[
'id' => 2,
'child_name' => "John",
'parent_name' => "Mr Brown",
],
[
'id' => 3,
'child_name' => "Joseph",
'parent_name' => "Mr Thomas",
],
[
'id' => 4,
'child_name' => "Pretty",
'parent_name' => "Mr Thomas",
],
[
'id' => 5,
'child_name' => "Raphel",
'parent_name' => "Mr Brown",
],
[
'id' => 6,
'child_name' => "Tommy",
'parent_name' => "Mr Thomas",
],
[
'id' => 7,
'child_name' => "Tim",
'parent_name' => "Mr Thomas",
],
[
'id' => 8,
'child_name' => "William",
'parent_name' => "",
],
];
$resultArray = [];
foreach ($array as $key => $value) {
if($value['parent_name'] != ''){
$resultArray[$value['parent_name']][] = $value;
}else{
$resultArray[$value['child_name']] = [];
}
}
$data = ['resultArray' => $resultArray];
$this->load->view('welcome_message', $data);
}
welcome_message.php (view)
<div>
<form name='sample'>
<?php
foreach ($resultArray as $parentKey => $parentValue) {
echo '<input type="checkbox" name="'.$parentKey.'" value="'.$parentKey.'">'.$parentKey.'<br>';
foreach ($parentValue as $childKey => $childValue) {
echo ' <input type="checkbox" name="'.$childValue['child_name'].'" value="'.$childValue['child_name'].'">'.$childValue['child_name'].'<br>';
}
}
?>
</form>
</div>
Output
Check this,
Loop your array, it will capture all values with same parent_name.
$result = [];
foreach ($array as $key => $value) {
$result[$value['parent_name']][] = $value['child_name']; // loop your array
}
It should work.

In php is there a function like array_column for multidimensional arrays [duplicate]

This question already has answers here:
How to group subarrays by a column value?
(20 answers)
Closed 2 years ago.
Is there function that works similar to array_column for multidimensional arrays? Is there a function that translates the first array below to the second:
Array
(
[0] => Array
(
[foodType] => fruits
[itemID] => 1
[itemName] => apple
)
[1] => Array
(
[foodType] => fruits
[itemID] => 2
[itemName] => banana
)
[2] => Array
(
[foodType] => veggies
[itemID] => 3
[itemName] => carrot
)
[3] => Array
(
[foodType] => veggies
[itemID] => 4
[itemName] => broccoli
)
)
Resulting array:
Array
(
[fruits] => Array
(
[0] => Array
(
[itemID] => 1
[itemName] => apple
)
[1] => Array
(
[itemID] => 2
[itemName] => banana
)
)
[veggies] => Array
(
[0] => Array
(
[itemID] => 3
[itemName] => carrot
)
[1] => Array
(
[itemID] => 4
[itemName] => broccoli
)
)
)
No, there is not a function to get your expected output natively, though you can make your own functions, just use array_column to get the types/column, and then loop over your array, on match remove the item as to not duplicate iterations.
Something like:
<?php
$data = [
['foodType' => 'fruits', 'itemID' => 1, 'itemName' => 'apple'],
['foodType' => 'fruits', 'itemID' => 2, 'itemName' => 'banana'],
['foodType' => 'veggies', 'itemID' => 3, 'itemName' => 'carrot'],
['foodType' => 'veggies', 'itemID' => 4, 'itemName' => 'broccoli']
];
function array_column_multi ($array, $column) {
$types = array_unique(array_column($array, $column));
$return = [];
foreach ($types as $type) {
foreach ($array as $key => $value) {
if ($type === $value[$column]) {
unset($value[$column]);
$return[$type][] = $value;
unset($array[$key]);
}
}
}
return $return;
}
print_r(array_column_multi($data, 'foodType'));
https://3v4l.org/KQVeN
Result:
Array
(
[fruits] => Array
(
[0] => Array
(
[itemID] => 1
[itemName] => apple
)
[1] => Array
(
[itemID] => 2
[itemName] => banana
)
)
[veggies] => Array
(
[0] => Array
(
[itemID] => 3
[itemName] => carrot
)
[1] => Array
(
[itemID] => 4
[itemName] => broccoli
)
)
)
Oh I just noticed that you're aggregating them by ID. There's not a function for that, you're going to need to iterate over the input with a loop, and populate an output array with the data you want. Eg:
$output = [];
foreach($input_array as $item) {
$output[$item['id']][] = [
'itemID' => $item['itemID'],
'itemName' => $item['itemName']
];
}
Quite old question, but I hope it help someone. Unfortunately there's no native function yet but output is achievable using php's array_filter():
$foods = [
[
'foodType' => 'fruits',
'itemID' => 1,
'itemName' => 'apple',
],
[
'foodType' => 'fruits',
'itemID' => 2,
'itemName' => 'banana',
],
[
'foodType' => 'veggies',
'itemID' => 3,
'itemName' => 'carrot',
],
[
'foodType' => 'veggies',
'itemID' => 4,
'itemName' => 'broccoli',
]
];
$grouped_foods = [];
$groupByColumn = 'foodType';
array_filter($foods, function ($foodItem) use(&$grouped_foods, $groupByColumn) {
$grouped_foods[$foodItem[$groupByColumn]][] = array_filter($foodItem, function ($key) use($groupByColumn) {
return $key != $groupByColumn;
}, ARRAY_FILTER_USE_KEY);
});
echo "<pre>";
print_R($grouped_foods);
echo "</pre>";
see in action: https://3v4l.org/bbX5A
Disclaimer: for/foreach loops are significantly faster in performance than native array functions.
I prefer using the following solution.
Example
"allergens" => array:5 [
0 => array:2 [
"id" => "10"
"object" => array:1 [
"allergens" => "10"
]
]
1 => array:2 [
"id" => "11"
"object" => array:1 [
"allergens" => "11"
]
]
2 => array:2 [
"id" => "4"
"object" => array:1 [
"allergens" => "4"
]
]
]
Giving this example, if you would like an array containing only the value of allergens then use the following code.
Solution
$allergens = array_map( function ( $ar ) {
return $ar['allergens'];
}, array_column( $allergensArr, 'object' ) );
Result
array:5 [
0 => "10"
1 => "11"
2 => "4"
]

Sorting a associative array based on two keys

I want to sort the id field by pushing array record with null value to bottom. If id value is present, then sort the col_1 by asc.
I have a multidimensional array like this.
Array
(
[0]=> Array
(
[id]=>1166
[col_1]=>9.4
)
[1]=> Array
(
[id]=>
[col_1]=>2.4
)
[2]=> Array
(
[id]=>1012
[col_1]=>0.96
)
[3]=> Array
(
[id]=>1856
[col_1]=>7.47
)
)
I want to sort it by id as well as col_1.
I tried
foreach ($arr as $key => $row) {
$x[$key] = $row['id'];
$y[$key] = $row['col_1'];
}
array_multisort($x, SORT_DESC, $y, SORT_ASC, $arr);
I got the following as my result
Array
(
[0]=> Array
(
[id]=>1856
[col_1]=>7.47
)
[1]=> Array
(
[id]=>1166
[col_1]=>9.4
)
[2]=> Array
(
[id]=>1012,
[col_1]=>0.96
)
[3]=> Array
(
[id]=>
[col_1]=>2.47
)
)
But I want the result as,
Array
(
[0]=> Array
(
[id]=>1012
[col_1]=>0.96
)
[1]=> Array
(
[id]=>1856
[col_1]=>7.47
)
[2]=> Array
(
[id]=>1166
[col_1]=>9.4
)
[3]=> Array
(
[id]=>
[col_1]=>2.4
)
)
'id' field can be null also for some records. But col_1 will be there for all the records.
Not exactly sophisticated, but readable and straight forward:
<?php
$data = [
[
'id' => 1166,
'col_1' => 9.4
],
[
'id' => null,
'col_1' => 2.4
],
[
'id' => 1012,
'col_1' => 0.96
],
[
'id' => 1856,
'col_1' => 7.47
]
];
usort($data, function($a, $b) {
return ($a['col_1']>$b['col_1']);
});
usort($data, function($a) {
return !isset($a['id']);
});
print_r($data);
The output obviously is:
Array
(
[0] => Array
(
[id] => 1012
[col_1] => 0.96
)
[1] => Array
(
[id] => 1856
[col_1] => 7.47
)
[2] => Array
(
[id] => 1166
[col_1] => 9.4
)
[3] => Array
(
[id] =>
[col_1] => 2.4
)
)
In your comment below you now make an additional requirement. I doubt there is a direct way to evaluate both requirements in a straight forward sorting approach. So why not try a readable and obvious one:
<?php
$data = [
[
'id' => 1166,
'col_1' => 9.4
],
[
'id' => null,
'col_1' => 2.4
],
[
'id' => null,
'col_1' => 0.2
],
[
'id' => 1012,
'col_1' => 0.96
],
[
'id' => null,
'col_1' => 12
],
[
'id' => 1856,
'col_1' => 7.47
]
];
usort($data, function($a, $b) {
return ($a['col_1']>$b['col_1']);
});
$withId = array_filter($data, function($entry) {
return isset($entry ['id']);
});
$withoutId = array_filter($data, function($entry) {
return !isset($entry ['id']);
});
$data = array_merge($withId, $withoutId);
print_r($data);
The output obviously is:
Array
(
[0] => Array
(
[id] => 1012
[col_1] => 0.96
)
[1] => Array
(
[id] => 1856
[col_1] => 7.47
)
[2] => Array
(
[id] => 1166
[col_1] => 9.4
)
[3] => Array
(
[id] =>
[col_1] => 0.2
)
[4] => Array
(
[id] =>
[col_1] => 2.4
)
[5] => Array
(
[id] =>
[col_1] => 12
)
)
you can use the usort function to make a custom sort.
function customSort($a, $b) {
if (null === $a['id'] && null === $b['id']) {
return 0;
}
if (null === $a['id']) {
return 1;
}
if (null === $b['id']) {
return -1;
}
return ($a['col_1'] < $b['col_1']) ? -1 : 1;
}
$array = [
[
'id' => 1012,
'col_1' => 0.96
],
[
'id' => 1856,
'col_1' => 7.47
],
[
'id' => null,
'col_1' => 2.4
],
[
'id' => 1166,
'col_1' => 9.4
],
];
usort($array, 'customSort');
print_r($array);
This returns
Array
(
[0] => Array
(
[id] => 1012
[col_1] => 0.96
)
[1] => Array
(
[id] => 1856
[col_1] => 7.47
)
[2] => Array
(
[id] => 1166
[col_1] => 9.4
)
[3] => Array
(
[id] =>
[col_1] => 2.4
)
)
Which is what you expected. Hope this helped.

PHP : merge multi arrays in sections

I load data from .xlsx sheet
And i convert it to two arrays
The first is the header columns
The second is the data columns
I did this
$c = array_combine($headers, $data);
when i print $c
Array
(
[id] => Array
(
[0] => 1
[1] => 2
)
[f-name] => Array
(
[0] => Mohammed
[1] => Ziad
)
[s-name] => Array
(
[0] => Amer
[1] => Mohammed
)
[t-name] => Array
(
[0] => Hendy
[1] => Shokry
)
[cid] => Array
(
[0] => 89
[1] => 55
)
)
i want to make the result like that
array(
[0] => Array(
[id] => 0
[f-name] => mohammed
[s-name] => amer
[t-name] => hendy
[cid] => 89
)
[1] => Array(
[id] => 1
[f-name] => ziad
[s-name] => mohammed
[t-name] => shokry
[cid] => 55
)
)
try this:
$data = array(
'id' => array
(
0 => 1,
1 => 2
),
'f-name' => array
(
0 => 'Mohammed',
1 => 'Ziad'
),
's-name' => array
(
0 => 'Amer',
1 => 'Mohammed'
),
't-name' => array
(
0 => 'Hendy',
1 => 'Shokry'
),
'cid' => array
(
0 => 89,
1 => 55
)
);
//
$result = array();
foreach($data as $k=>$v){
for($i=0;$i<count($data['id']);$i++){
//$v[$i] = ($k!='id') ?: $i;// uncomment for reset id from 0
$result[$i][$k] = $v[$i];
}
}
var_dump($result);
result:
array (size=2)
0 =>
array (size=5)
'id' => int 1
'f-name' => string 'Mohammed' (length=8)
's-name' => string 'Amer' (length=4)
't-name' => string 'Hendy' (length=5)
'cid' => int 89
1 =>
array (size=5)
'id' => int 2
'f-name' => string 'Ziad' (length=4)
's-name' => string 'Mohammed' (length=8)
't-name' => string 'Shokry' (length=6)
'cid' => int 55
Try something like this:
for ($index = 0; &index < 2; ++$index)
{
thing['id'] = $index;
thing['f-name'] = $c['f-name'];
thing['l-name'] = $c['s-name'];
thing['t-name'] = $c['t-name'];
thing['cid'] = $c['cid'];
$newArra y[$index] = thing;
}
I like to include "fancy" array functions like array_walk and array_map whenever I have the chance:
Initialize your data
$data = [
'id' => [
0 => 1,
1 => 2
],
'f-name' => [
0 => 'Mohammed',
1 => 'Ziad'
],
's-name' => [
0 => 'Amer',
1 => 'Mohammed'
],
't-name' => [
0 => 'Hendy',
1 => 'Shokry'
],
'cid' => [
0 => 89,
1 => 55
]
];
Transform the data
$result = [];
array_walk($data['id'],
function($f, $i) use ($data, &$result){
$result[$i] = array_map(function($e) use ($i){
return $e[$i];
}, $data);
}
);
Output the result
var_dump($result);
array(2) {
[0]=>
array(5) {
["id"]=>
int(1)
["f-name"]=>
string(8) "Mohammed"
["s-name"]=>
string(4) "Amer"
["t-name"]=>
string(5) "Hendy"
["cid"]=>
int(89)
}
[1]=>
array(5) {
["id"]=>
int(2)
["f-name"]=>
string(4) "Ziad"
["s-name"]=>
string(8) "Mohammed"
["t-name"]=>
string(6) "Shokry"
["cid"]=>
int(55)
}
}

Categories