Muhammad Sanaullah
Muhammad Sanaullah

Reputation: 455

Array Combine with same year

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

Answers (6)

Progrock
Progrock

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

The fourth bird
The fourth bird

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

aaronfc
aaronfc

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:

  • As others suggested: create a new structure for your output. Reusing the same array will probably cause you nightmares. What if you want to later use the original input? Check inmutability and stateless programming.
  • It is easier if you use a map/dictionary/associative-array for grouping instead of an array itself. It is easier (and faster) to check if a key exists in a map than if an element exists in an array.
  • All this is using basic php/programming stuff. It can also be achieved by using array_reduce. If you are curious take a look at it :)

Give the code and comments a look and if you have any doubt let me know.

Upvotes: 1

Jhecht
Jhecht

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.

Edit

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

Nick
Nick

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

Demo on 3v4l.org

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);

Demo on 3v4l.org

Upvotes: 2

Nerea
Nerea

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

Related Questions