23

I have a array like this:

$str=
   Array
(
    [No] => 101
    [Paper_id] => WE3P-1
    [Title] => "a1"
    [Author] => ABC
    [Aff_list] => "University of South Florida, Tampa, United States"
    [Abstracts] => "SLA"

)

Array
(
    [No] => 101
    [Paper_id] => WE3P-1
    [Title] => "a2"
    [Author] => DEF
    [Aff_list] => "University of South Florida, Tampa, United States"
    [Abstracts] => "SLA "

)

Array
(
    [No] => 104
    [Paper_id] => TU5A-3
    [Title] => "a3"
    [Author] => GHI
    [Aff_list] => "University of Alcala, Alcala de Henares, Spain"
    [Abstracts] => "Microwave"

)

I want to group elements in the array based upon 'No' as primary key. The output should look like this:

 array(6) {
  ["No"]=>
  string(6) "101"
  ["Paper_id"]=>
  string(6) "WE3P-1"
  ["Title"]=>
  string(80) ""a-1"
  ["Author"]=>
  string(14) "ABC"
  ["Aff_list"]=>
  string(51) ""University of South Florida, Tampa, United States""
  ["Abstracts"]=>
  string(5) ""(SLA)"
"
}
array(6) {
  ["No"]=>
  string(3) "104"
  ["Paper_id"]=>
  string(6) "TU5A-3"
  ["Title"]=>
  string(40) "a2"
  ["Author"]=>
  string(20) "DEF"
  ["Aff_list"]=>
  string(48) ""University of Alcala, Alcala de Henares, Spain""
  ["Abstracts"]=>
  string(9) ""Microwave"
"
}

Note that the Author's value got merged with respect to the primary key 'No'.Can anyone help me out from this, please?

I tried doing this:

foreach($paper_info as $element) {
    foreach($element as $v) {
        $id = $element['No'];
        if (!isset($out[$id])) {
            $out[$id] = [
                'No' => $element['No'],
                'Paper_id' => $element['Paper_id'],
                'Title' => $element['Title'],
                'Authors' => [],
                'Aff_list' => $element['Aff_list'],
                'Abstracts' => $element['Abstracts']
            ];
        }
        $out[$id]['Authors'][] = ['Authors' => $element['Author']];
    }
}
Chemaclass
  • 1,933
  • 19
  • 24
Aditya
  • 4,453
  • 3
  • 28
  • 39
  • what's wrong with the output of your code you tried? apart from the `out` variable missing the $ – Levi Jan 01 '13 at 19:04
  • Its printing empty array! :( – Aditya Jan 01 '13 at 19:10
  • Why does `101`'s `title` become `""a-1"` when merging `a1` and `a2`?!? Why does `104`'s `title` become `a2` when it was originally `a3`?!? This is not a good [mcve]. – mickmackusa Dec 05 '20 at 13:18

5 Answers5

67

You could use a generic function:

function _group_by($array, $key) {
    $return = array();
    foreach($array as $val) {
        $return[$val[$key]][] = $val;
    }
    return $return;
}

I added some sample code to test

<?php

$list= [
[   'No' => 101,
    'Paper_id' => 'WE3P-1',
    'Title' => "a1",
    'Author' => 'ABC',
    'Aff_list' => "University of South Florida, Tampa, United States",
    'Abstracts' => "SLA"
] ,
[   'No' => 101,
    'Paper_id' => 'WE3P-1',
    'Title' => "a2",
    'Author' => 'DEF',
    'Aff_list' => "University of South Florida, Tampa, United States",
    'Abstracts' => "SLA"
] ,
[    'No' => 104, 
    'Paper_id' => 'TUSA-3',
    'Title' => "a3",
    'Author' => 'GH1',
    'Aff_list' => "University of Alcala, Alcala de Henares, Spain",
    'Abstracts' => "Microwave"
] ];

print_r(_group_by($list, 'No'));
crafter
  • 6,246
  • 1
  • 34
  • 46
6

The data format in your question is ambiguous, but assuming the structure for $paper_info is what is below, this should get you the output you're looking for.

$paper_info = array(
    array(
        'No' => "101",
        'Paper_id' => "WE3P-1",
        'Title' =>"An Electrically-Small, 3-D Cube Antenna Fabricated with Additive Manufacturing",
        'Author' => "Ibrahim Nassar",
        ...
    ),
    array(
        'No' => "101",
        ...
        'Author' => "Thomas Weller",
        ...
    )
);

$out = array();
foreach($paper_info as $paper) {
    $id = $paper['No'];
    if (!isset($out[$id])) {
        $out[$id] = $paper;
        $out[$id]['Author'] = array();
    }
    $out[$id]['Author'][] = $paper['Author'];
}

You should also turn on warnings and display errors in your development environment. I have a feeling it will help you. During development you can either configure your php.ini, or insert this code at the beginning of your php script. Just make sure you remove it before pushing to production.

error_reporting(E_ALL);
ini_set('display_errors', '1');
Levi
  • 2,103
  • 14
  • 9
  • Its saying: Warning: Illegal string offset 'No' Illegal string offset 'Author' – Aditya Jan 01 '13 at 19:42
  • 1
    That means your data is not in the format I assumed and specified above. I would help if you provided a valid code sample in your question that will create the variable $paper_info in the proper format. – Levi Jan 01 '13 at 19:47
  • $paper_info is an array of arrays like 'No' => $a (which is an array of nos) , 'Paper_id' =>$b (array of ids).. similar for all other keys – Aditya Jan 01 '13 at 19:56
  • If the error you mentioned happened first on line `$id = $paper['No']`, that would suggest that $paper_info is actually an array of strings. – Levi Jan 01 '13 at 19:57
2

Thanks to crafter for the awesome function, if someone need to group for multiple keys i edited the crafter function to this:

function _group_by($array, $keys=array()) {
    $return = array();
    foreach($array as $val){
        $final_key = "";
        foreach($keys as $theKey){
            $final_key .= $val[$theKey] . "_";
        }
        $return[$final_key][] = $val;
    }
   return $return;
}
0

Thanks to crater and Fabio's answer. I updated the code to check if the size of the key is not greater than one (1), underscore will not be appended.

function _group_by($array, $keys=array()) {
    $return = array();
    $append = (sizeof($keys) > 1 ? "_" : null);
    foreach($array as $val){
        $final_key = "";
        foreach($keys as $theKey){
            $final_key .= $val[$theKey] . $append;
        }
        $return[$final_key][] = $val;
    }
    return $return;
}
0

I have wrote an another version of Crafter's answer which is remove given key from actual array. May help someone.

    public function _group_by($array, $key) {
        $return = array();
        foreach($array as $val) {
            $return[$val[$key]] = $val;
            unset($return[$val[$key]][$key]);
        }
        return $return;
    }