在PHP中,如何根据键对数组值进行分组?

23

我有一个像这样的数组:

$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"

)

我希望根据“No”作为主键,将数组中的元素进行分组。输出应该如下所示:

 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"
"
}
请注意,作者的值已根据主键“No”合并。请问有谁可以帮我解决这个问题吗?
我尝试了以下操作:
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']];
    }
}

你的代码输出有什么问题?除了缺少$符号的out变量之外。 - Levi
它正在打印空数组!:( - Aditya
当合并a1a2时,为什么101title变成了""a-1"?!?当104最初是a3时,为什么它的title变成了a2?!?这不是一个好的[mcve]。 - mickmackusa
5个回答

67

你可以使用一个通用函数:

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

我添加了一些示例代码进行测试
<?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'));

6

您提出的问题中数据格式不明确,但是假设$paper_info的结构如下所示,这将为您提供所需的输出。

$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'];
}

在开发环境中,您还应该打开警告和显示错误。我觉得这会对您有所帮助。在开发过程中,您可以配置php.ini,或将此代码插入到您的php脚本开头。只需确保在推送到生产之前将其删除。

error_reporting(E_ALL);
ini_set('display_errors', '1');

警告:非法字符串偏移量 'No' 非法字符串偏移量 'Author' - Aditya
1
这意味着您的数据不符合我上面所假定和指定的格式。如果您在问题中提供一个有效的代码示例,可以创建变量$paper_info以正确的格式,那么我会提供帮助。 - Levi
$paper_info是一个数组,其中包含类似于'No' => $a(它是一组编号的数组),'Paper_id' =>$b(它是一组ID的数组)的数组。所有其他键也是类似的。 - Aditya
如果你提到的错误第一次发生在$id = $paper ['No']这一行,那就说明$paper_info实际上是一个字符串数组。 - Levi

2

感谢crafter提供的出色函数,如果有人需要为多个键分组,我将crafter函数编辑为以下内容:

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

我写了 Crafter 的答案的另一个版本,可以从实际数组中删除给定的键。希望能对某些人有所帮助。

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

0
感谢crater和Fabio的回答。我更新了代码,检查键的大小是否不大于1,如果是,则不会附加下划线。
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接