Reputation: 455
I hope you guys fine, From last 3-4 hours I try to combine year in the same array set and unset all other arrays which are duplicate (I unable to explain correctly, please check the array example below)., but so far no luck, I tried and I know this isn't the correct way, if anybody has a solution for this please share.
Can somebody tell me how to combine same year in an array and unset other arrays at the same time, I tried but failed, no luck.
Try to do that way, but faild misrably:
foreach ($class as $i=>$class_list){
echo $i;
foreach ($class_list as $key=>$value){
$e=0;
foreach ($class_list as $value2){
if ($value['name']==$value2['name']){
echo 'match';
$class['packages'][$key]['year'][$e]=$value['year'];
}
$e++;
}
}
}
Actual Array:
Array
(
[packages] => Array
(
[0] => Array
(
[name] => atif.ali
[year] => 2019
)
[1] => Array
(
[name] => atif.ali
[year] => 2018
)
[2] => Array
(
[name] => atif.ali
[year] => 2017
)
[3] => Array
(
[name] => khatija.abbas
[year] => 2017
)
)
)
Need output like this:
Array
(
[packages] => Array
(
[0] => Array
(
[name] => atif.ali
[year] => Array
(
[0] 2019
[1] 2018
[2] 2017
)
)
[1] => Array
(
[name] => khatija.abbas
[year] => 2017
)
)
)
P.S: array can be different but "year" and "name" structure always same.
Upvotes: 1
Views: 70
Reputation: 7485
Here is an example, just build a new array and swap.
<?php
$data =
[
[
'name' => 'Bilbo Baggins',
'year' => 2010
],
[
'name' => 'Bilbo Baggins',
'year' => 2011
],
[
'name' => 'Frodo Baggins',
'year' => 1999
]
];
foreach($data as $item) {
$output[$item['name']]['name'] = $item['name'];
$output[$item['name']]['year'][] = $item['year'];
}
print_r($output);
Output:
Array
(
[Bilbo Baggins] => Array
(
[name] => Bilbo Baggins
[year] => Array
(
[0] => 2010
[1] => 2011
)
)
[Frodo Baggins] => Array
(
[name] => Frodo Baggins
[year] => Array
(
[0] => 1999
)
)
)
If you don't like the new keys, call array_values
on the result.
Upvotes: 0
Reputation: 163207
Another option is to create a new result where the key packages
already exists. Then use the name as the key so you can check if the key already exists.
If it does not, add a new entry. If it does already exists, index into the new $result
converting what is already there to an array so that the first entry which is a string becomes an array.
$arrays = [
"packages" => [
["name" => "atif.ali", "year" => "2019"],
["name" => "atif.ali", "year" => "2018"],
["name" => "atif.ali", "year" => "2017"],
["name" => "khatija.abbas", "year" => "2019"]
]
];
$result = ["packages" => []];
foreach ($arrays["packages"] as $array) {
if(!array_key_exists($array['name'], $result["packages"])) {
$result["packages"][$array['name']] = $array;
continue;
}
$result["packages"][$array['name']]['year'] = (array)$result["packages"][$array['name']]['year'];
$result["packages"][$array['name']]['year'][] = $array['year'];
}
print_r($result);
See a php demo
If you want numerical indexes instead, you could use array_values like this example
Upvotes: 1
Reputation: 165
I see there are some other responses while I wrote my own. First of all here you have the piece of code:
<?php
// Input data
$input = array('packages' => array(
array('name' => 'atif.ali', 'year' => 2019),
array('name' => 'atif.ali', 'year' => 2018),
array('name' => 'atif.ali', 'year' => 2017),
array('name' => 'khatija.abbas', 'year' => 2017),
));
$output = array(); // Create new array to store the final result
foreach ($input['packages'] as $package) { // we are only interested in 'packages', let's iterate over them
$name = $package['name'];
$year = $package['year'];
if (!isset($output[$name])) { // First time we see this name?
$output[$name] = array('name' => $name, 'year' => []); // Let's create an "empty" structure.
}
if (!in_array($year, $output[$name]['year'])) { // First time we see this year for this name?
$output[$name]['year'][] = $year; // Let's add it
}
}
// Reformatting to fit your needs (nest everything under 'packages' and remove the names from resulting dictionary keys)
$output = array('packages' => array_values($output));
var_dump($output);
Let me note the key issues/concepts:
Give the code and comments a look and if you have any doubt let me know.
Upvotes: 1
Reputation: 4435
I've written this sort of quickly -- I'll look at it again in the morning when I've hopefully had a chance to rest and rethink how to do this with one loop. This seems to work for me. NOTE I did not include the 'packages' key, but the code can be modified by adding it in front of that particular section.
Had a quick second to think about what I did, perhaps this is what you're looking for:
<?php
$raw = [
[
'name'=>'atif.ali',
'year'=>2018
],
[
'name'=>'atif.ali',
'year'=>2019
],
[
'name'=>'atif.ali',
'year'=>2017
],
[
'name'=>'kahitja.abal',
'year'=>2019
],
[
'name'=>'kahitja.abal',
'year'=>2018
],
[
'name'=>'john.smith',
'year'=>2017
],
[
'name'=>'john.smith',
'year'=>2018
],
];
$map_index = [];
$final = [];
for($i = 0; $i< count($raw); $i++) {
if(!isset($map_index[$raw[$i]['name']])){
$map_index[$raw[$i]['name']] = count($final);
$final[count($final)] = ['name'=>$raw[$i]['name'], 'years'=>[]];
}
$index = $map_index[$raw[$i]['name']];
$final[$index]['years'][]=$raw[$i]['year'];
}
echo '<pre>';
print_r($final);
?>
Upvotes: 0
Reputation: 147146
It's probably easiest to just create a new array in the format you require. You can do that by looping over the values inside packages
, checking for the existence of the name
in the new array, and if it exists, adding the current year to that value. If it doesn't exist, just create a new entry for that name.
$new_array = array('packages' => array());
foreach ($array['packages'] as $value) {
if (($k = array_search($value['name'], array_column($new_array['packages'], 'name'))) !== false) {
$new_array['packages'][$k]['year'][] = $value['year'];
}
else {
$new_array['packages'][] = array('name' => $value['name'], 'year' => array($value['year']));
}
}
print_r($new_array);
Output:
Array
(
[packages] => Array
(
[0] => Array
(
[name] => atif.ali
[year] => Array
(
[0] 2019
[1] 2018
[2] 2017
)
)
[1] => Array
(
[name] => khatija.abbas
[year] => Array (
[0] => 2017
)
)
)
)
Update
If you really want the year
field not to be an array when there is only one value, this code will do that for you; it only makes it into an array when a second or subsequent value is seen.
$new_array = array('packages' => array());
foreach ($array['packages'] as $value) {
if (($k = array_search($value['name'], array_column($new_array['packages'], 'name'))) !== false) {
if (is_array($new_array['packages'][$k]['year'])) {
$new_array['packages'][$k]['year'][] = $value['year'];
}
else {
$new_array['packages'][$k]['year'] = array($new_array['packages'][$k]['year'], $value['year']);
}
}
else {
$new_array['packages'][] = $value;
}
}
print_r($new_array);
Upvotes: 2
Reputation: 2147
Try this
$class = ['packages' => [['name' => 'atif.ali', 'year' => 2019], ['name' => 'atif.ali', 'year' => 2018], ['name' => 'atif.ali', 'year' => 2017], ['name' => 'khatija.abbas', 'year' => 2017]]];
$new_class = [];
foreach ($class['packages'] as $key => $class_list) {
if( ! isset($new_class[$class_list['name']])){
$new_class[$class_list['name']] = $class_list;
}else{
if(is_array($new_class[$class_list['name']]['year'])){
$new_class[$class_list['name']]['year'][] = $class_list['year'];
}else{
$prev_year = $new_class[$class_list['name']]['year'];
$new_class[$class_list['name']]['year'] = [$prev_year, $class_list['year']];
}
}
}
$class['packages'] = $new_class;
Upvotes: 1