How to get certain values from multidimensional arrays? - php

Here's the data I am working with right now:
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
I would like to get a list of data associated with only "name" key.
I would also like to show the data associated with "area" key once the user go for the corresponding "name".
It would be helpful if there were any suggestion on how to better store this data for frequent usage in code.

As long as the names are unique you can do this simple trick:
Example 1
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
$names = array_column($city, null, 'name');
print_r($names);
Output
Array
(
[Dhaka] => Array
(
[name] => Dhaka
[areas] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
)
[Chittagong] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => c1
[1] => c2
[2] => c3
)
)
[Sylhet] => Array
(
[name] => Sylhet
[areas] => Array
(
[0] => s1
[1] => s2
[2] => s3
)
)
[Barisal] => Array
(
[name] => Barisal
[areas] => Array
(
[0] => b1
[1] => b2
[2] => b3
)
)
[Khulna] => Array
(
[name] => Khulna
[areas] => Array
(
[0] => k1
[1] => k2
[2] => k3
)
)
[Rajshahi] => Array
(
[name] => Rajshahi
[areas] => Array
(
[0] => r1
[1] => r2
[2] => r3
)
)
)
Now you can lookup by name
print_r($city['Chittagong']['areas']); //["c1", "c2", "c3"]
If the names are not guaranteed to be unique, you'll have to build them using foreach, like this:
Example 2
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[ /*--- ADDED to show duplication ---- */
"name" => "Chittagong",
"areas" => ["x1", "x2", "x3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
$output = [];
foreach($city as $k=>$v){
$k = $v['name'];
if(!isset($output[$k])) $output[$k] = []; //initialize
$output[$k][] = $v;
}
print_r($output);
Which will give you something like this:
Array
(
[Dhaka] => Array
(
[0] => Array
(
[name] => Dhaka
[areas] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
)
)
[Chittagong] => Array
(
[0] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => c1
[1] => c2
[2] => c3
)
)
[1] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => x1
[1] => x2
[2] => x3
)
)
)
[Sylhet] => Array( ... )
As you can see this adds an extra level in to contain the multiple occurrences. Of course you could just combine the area when duplicate (in the foreach). But that is up to you.
Here is a quick example of that (same data as above):
Example 3
$output = [];
foreach($city as $k=>$v){
$k = $v['name'];
if(!isset($output[$k])) $output[$k] = []; //initialize
$output[$k] = array_merge($output[$k], $v['areas']); //merge the areas
}
print_r($output);
Output
Array
(
[Dhaka] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
[Chittagong] => Array
(
[0] => c1
[1] => c2
[2] => c3
[3] => x1
[4] => x2
[5] => x3
)
....
)
If it was me, I would go with the last one, just because of the simplicity it will have working with it later.
PS. if your pulling data out of a Database with PDO, you can use $stmt->fetchAll(PDO::FETCH_GROUP) which will give you something like the second example automatically. The only caveat here is that the name column is the first one selected in the Query, which is the column it will group on.
Cheers.

If you're just trying to loop through the list of cities and get the names you can just use a foreach loop. If you need something beyond this try to define your question a little more.
foreach ($city as $c) {
echo $c["name"];
}

Related

Change specific value in Dynamic nested array with parent and children structure PHP

I have a dynamic nested array structure with unique id and name, need to change value of name for a specific id given.
I have a dynamic nested array with structure
`
$array = [
[
"id" => "31350880",
"name" => "HOD",
"children" => [
[
"id" => "57f94cd7",
"parent_id" => "31350880",
"name" => "New HOD",
"children" => [
[
"id" => "e7f1c88b",
"parent_id" => "57f94cd7",
"name" => "Gold",
"children" => [
]
]
]
]
]
],
[
"id" => "45881fa8",
"name" => "Pictures",
"children" => [
[
"id" => "770e6e20",
"parent_id" => "45881fa8",
"name" => "New Picture",
"children" => [
[
"id" => "a403a8fa",
"parent_id" => "770e6e20",
"name" => "Silver",
"children" => [
]
]
]
]
]
]
];
`
For a given ID(unique) , need to find it from array and change the name from that node to a specific name.
for example : $id = ''770e6e20' which is a child of parent node with name "Pictures", need to find child node with specific id and change its name and retrieve the full array in its initial structure ?
This is a recursive function that gets a reference of your array, the id of the item and the new name to be assigned, and performs in place modification:
function modify_element_name(&$arr, $id, $name){
foreach($arr as $index => $item){
if($item['id'] === $id){
$arr[$index]['name'] = $name;
}
else {
if(count($item['children']) > 0){
modify_element_name($arr[$index]['children'], $id, $name);
}
}
}
}
Calling it as below:
modify_element_name($array, '770e6e20', 'New Picture Modified');
Will modify the array:
Array
(
[0] => Array
(
[id] => 31350880
[name] => HOD
[children] => Array
(
[0] => Array
(
[id] => 57f94cd7
[parent_id] => 31350880
[name] => New HOD
[children] => Array
(
[0] => Array
(
[id] => e7f1c88b
[parent_id] => 57f94cd7
[name] => Gold
[children] => Array
(
)
)
)
)
)
)
[1] => Array
(
[id] => 45881fa8
[name] => Pictures
[children] => Array
(
[0] => Array
(
[id] => 770e6e20
[parent_id] => 45881fa8
[name] => New Picture Modified
[children] => Array
(
[0] => Array
(
[id] => a403a8fa
[parent_id] => 770e6e20
[name] => Silver
[children] => Array
(
)
)
)
)
)
)
)

How to change the collection on the basis of array in column value

I want to change the laravel collection because I want to pass this collection to generate report.
How to change collection on the basis of the value in the column.
Previous:
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => stdClass Object
(
[id] => 23
[form_type] => radio
[details] => [{"id":55 title:"AA" name:"BB"}, {"id":56 title:"CC" name:"DD"}]
)
[1] => stdClass Object
(
[id] => 24
[form_type] => checkbox
[details] => [{"id":57 title:"PP" name:"QQ"}, {"id":58 title:"RR" name:"SS"}]
)
)
)
--details column has array of objects, I want it as below format:
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => stdClass Object
(
[id] => 23
[form_type] => radio
[title] => "AA"
[name] => "BB"
)
[1] => stdClass Object
(
[id] => 23
[form_type] => radio
[title] => "CC"
[name] => "DD"
)
[2] => stdClass Object
(
[id] => 24
[form_type] => checkbox
[title] => "PP"
[name] => "QQ"
)
[4] => stdClass Object
(
[id] => 24
[form_type] => checkbox
[title] => "RR"
[name] => "SS"
)
)
)
The only way is to use each method of Laravel collection. I expect the data in the following format and you will get the desired output.
$data = collect([
(object)["id" => 23, "form_type" => "radio", "details" => [["id" => 55, 'title' => "AA", 'name' => "BB"], ["id" => 56, 'title' => "CC", 'name' => "DD"]]]
]);
$result = collect();
$data->each(function($d) use ($result) {
$d = collect($d);
unset($t['id']);
$tmp = collect($d['details']);
$tmp->each(function($t) use (&$d, $result) {
$result->push($d->forget('details')->merge($t));
});
});
echo "<pre>";
print_r($result);
try this with ->map() function then ->push() into new collection
$data = [
[
"id" => 23,
"form_type" => "radio",
"details" => [["id" => 55, "title" => "AA", "name" => "BB"], ["id" => 56, "title" => "CC", "name" => "DD"]]
],
[
"id" => 24,
"form_type" => "checkbox",
"details" => [["id" => 57, "title" => "PP", "name" => "QQ"], ["id" => 58, "title" => "RR", "name" => "SS"]]
],
];
$data = collect($data);
$final = collect();
$data->map(function ($row) use ($data, $final) {
return collect($row['details'])->map(function ($item) use ($data, $row, $final) {
$parentData = $data->where('id', $row['id'])->first();
$final->push([
'id' => $parentData['id'],
'title' => $item['title'],
'form_type' => $parentData['form_type'],
'name' => $item['name']
]);
});
});
return $final;

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.

Sort an associative array by group with random group ordering

I have an associative array key/values indicating a group. I'd like to shuffle the array so that the groups are in a random order but so that the items in the groups are shuffled only within their group. In other words, I want to take something like this:
[
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Spike",
"group" => 3
]
]
And return something a bit more like this:
[
[
"name" => "Spike",
"group" => 3
]
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
]
I realise this is probably possible with two or three sorts, but it would be great if this could be done with a single usort.
Basically, my solution shuffles the input array, temporarily restructures the input array to gather subarrays with the same group value, then returns the data to its original structure.
Code: (Demo)
shuffle($data); // randomize all subarrays
foreach ($data as $set) {
$grouped[$set['group']][] = $set; // merge subarrays on group value
}
$output = [];
foreach($grouped as $group) {
array_push($output, ...$group); // return to original array structure
}
var_export($output);
*Note that ... (splat operator) allows array_push() to store all subarrays (within each group) individually to generate the original structure.
Possible Output:
array (
0 =>
array (
'name' => 'Xander',
'group' => 2,
),
1 =>
array (
'name' => 'Giles',
'group' => 2,
),
2 =>
array (
'name' => 'Willow',
'group' => 1,
),
3 =>
array (
'name' => 'Buffy',
'group' => 1,
),
4 =>
array (
'name' => 'Spike',
'group' => 3,
),
5 =>
array (
'name' => 'Tara',
'group' => 3,
),
6 =>
array (
'name' => 'Angel',
'group' => 3,
),
)
Try...
$groups = [];
foreach (array_unique(array_column($myar, 'group')) as $k) $groups[$k] = rand();
foreach (array_keys($myar) as $k) $myar[$k]['rnd'] = rand();
usort($myar, function($a, $b) use ($groups) {
if ($gdif = $groups[$b['group']] - $groups[$a['group']]) return $gdif;
return $b['rnd'] - $a['rnd'];
});
foreach (array_keys($myar) as $k) unset($myar[$k]['rnd']);
print_r($myar);
Run with your data, this is one result...
Array
(
[0] => Array
(
[name] => Buffy
[group] => 1
)
[1] => Array
(
[name] => Willow
[group] => 1
)
[2] => Array
(
[name] => Angel
[group] => 3
)
[3] => Array
(
[name] => Tara
[group] => 3
)
[4] => Array
(
[name] => Spike
[group] => 3
)
[5] => Array
(
[name] => Giles
[group] => 2
)
[6] => Array
(
[name] => Xander
[group] => 2
)
)

associative array check any column is empty or not

I have associative array like -
[0] => Array
(
[date] => 2018-06-22
[id] => 2282991
[type] => VIDEO
[domain] =>
[code] => Austin
[address] => Phone
)
[1] => Array
(
[date] => 2018-06-22
[id] => 2282991
[type] => VIDEO
[domain] =>
[code] =>
[address] => Phone
)
[3] => Array
(
[date] => 2018-06-22
[id] => 2282991
[type] => VIDEO
[domain] =>
[code] => Austin
[address] => Phone
)
I need to check is there any column having all the values are blank.
That means it should return only domain from above array because it is blank everywhere.
Is there any way to do this with minimum use of forloop? I need to check this for all these columns.
This will work if your subarray having same number of keys.Like "Date, id, Type etc".
$array = [
[ "date" => "2018-06-22", "id" => 2282991, "type" => "VIDEO", "domain" =>'', "code" => "Austin", "address" => "Phone"],
[ "date" => "2018-06-22", "id" => 2282991, "type" => "VIDEO", "domain" =>'', "code" => "", "address" => "Phone"],
[ "date" => "2018-06-22", "id" => 2282991, "type" => "VIDEO", "domain" =>'', "code" => "Austin", "address" => "Phone"]
];
$empty = [];
foreach($array[0] as $key=>$val){
$error = array_column($array, $key);
if(empty (array_filter($error)) ) {
$empty[] = $key;
}
}
print_r($empty);
Output:
Array
(
[0] => domain
)

Categories