我有以下数组
Array
(
[0] => Array
(
[id] => 96
[shipping_no] => 212755-1
[part_no] => reterty
[description] => tyrfyt
[packaging_type] => PC
)
[1] => Array
(
[id] => 96
[shipping_no] => 212755-1
[part_no] => dftgtryh
[description] => dfhgfyh
[packaging_type] => PC
)
[2] => Array
(
[id] => 97
[shipping_no] => 212755-2
[part_no] => ZeoDark
[description] => s%c%s%c%s
[packaging_type] => PC
)
)
如何按id
对数组进行分组?是否有任何本机PHP功能可用于此?
如果我foreach
以上那么我会得到一个重复的,我该如何避免?
在上面的示例id
中有2个项目,因此需要在id
内。
编辑:一切工作都很精细:但是有什么办法可以用一个方法来实现相同的目标吗?
答案 0 :(得分:112)
没有原生的,只需使用循环。
$result = array();
foreach ($data as $element) {
$result[$element['id']][] = $element;
}
答案 1 :(得分:30)
您可以尝试以下操作:
$group = array();
foreach ( $array as $value ) {
$group[$value['id']][] = $value;
}
var_dump($group);
输出:
array
96 =>
array
0 =>
array
'id' => int 96
'shipping_no' => string '212755-1' (length=8)
'part_no' => string 'reterty' (length=7)
'description' => string 'tyrfyt' (length=6)
'packaging_type' => string 'PC' (length=2)
1 =>
array
'id' => int 96
'shipping_no' => string '212755-1' (length=8)
'part_no' => string 'dftgtryh' (length=8)
'description' => string 'dfhgfyh' (length=7)
'packaging_type' => string 'PC' (length=2)
97 =>
array
0 =>
array
'id' => int 97
'shipping_no' => string '212755-2' (length=8)
'part_no' => string 'ZeoDark' (length=7)
'description' => string 's%c%s%c%s' (length=9)
'packaging_type' => string 'PC' (length=2)
答案 2 :(得分:17)
我只是在.NET LINQ
的启发下将它们整合在一起<?php
// callable type hint may be "closure" type hint instead, depending on php version
function array_group_by(array $arr, callable $key_selector) {
$result = array();
foreach ($arr as $i) {
$key = call_user_func($key_selector, $i);
$result[$key][] = $i;
}
return $result;
}
$data = array(
array(1, "Andy", "PHP"),
array(1, "Andy", "C#"),
array(2, "Josh", "C#"),
array(2, "Josh", "ASP"),
array(1, "Andy", "SQL"),
array(3, "Steve", "SQL"),
);
$grouped = array_group_by($data, function($i){ return $i[0]; });
var_dump($grouped);
?>
瞧,你得到了
array(3) {
[1]=>
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
string(4) "Andy"
[2]=>
string(3) "PHP"
}
[1]=>
array(3) {
[0]=>
int(1)
[1]=>
string(4) "Andy"
[2]=>
string(2) "C#"
}
[2]=>
array(3) {
[0]=>
int(1)
[1]=>
string(4) "Andy"
[2]=>
string(3) "SQL"
}
}
[2]=>
array(2) {
[0]=>
array(3) {
[0]=>
int(2)
[1]=>
string(4) "Josh"
[2]=>
string(2) "C#"
}
[1]=>
array(3) {
[0]=>
int(2)
[1]=>
string(4) "Josh"
[2]=>
string(3) "ASP"
}
}
[3]=>
array(1) {
[0]=>
array(3) {
[0]=>
int(3)
[1]=>
string(5) "Steve"
[2]=>
string(3) "SQL"
}
}
}
答案 3 :(得分:11)
在更具功能性的编程风格中,您可以使用array_reduce
$groupedById = array_reduce($data, function (array $accumulator, array $element) {
$accumulator[$element['id']][] = $element;
return $accumulator;
}, []);
答案 4 :(得分:4)
我也需要这样的功能。我创建了这个,你传递了你要分组的列:
function array_group(array $data, $by_column)
{
$result = [];
foreach ($data as $item) {
$column = $item[$by_column];
unset($item[$by_column]);
if (isset($result[$column])) {
$result[$column][] = $item;
} else {
$result[$column] = array($item);
}
}
return $result;
}
答案 5 :(得分:3)
for($i = 0 ; $i < count($arr) ; $i++ )
{
$tmpArr[$arr[$i]['id']] = $arr[$i]['id'];
}
$vmpArr = array_keys($tmpArr);
print_r($vmpArr);
答案 6 :(得分:3)
此array_group_by功能可实现您的目标:
$grouped = array_group_by($arr, 'id');
它甚至支持多级分组:
$grouped = array_group_by($arr, 'id', 'part_no');
答案 7 :(得分:3)
<强> 1。 GROUP BY
一键
此函数作为数组的GROUP BY
,但有一个重要的限制:只有一个分组“列”($identifier
)是可能的。
function arrayUniqueByIdentifier(array $array, string $identifier)
{
$ids = array_column($array, $identifier);
$ids = array_unique($ids);
$array = array_filter($array,
function ($key, $value) use($ids) {
return in_array($value, array_keys($ids));
}, ARRAY_FILTER_USE_BOTH);
return $array;
}
<强> 2。检测表(二维数组)的唯一行
此功能用于过滤“行”。如果我们说,一个二维数组是一个表,那么它的每个元素都是一行。因此,我们可以使用此功能删除重复的行。如果所有列(第二维的元素)相等,则两行(第一维的元素)相等。对“列”值的比较适用:如果值为简单type,则值本身将用于比较;否则将使用其类型(array
,object
,resource
,unknown type
)。
策略很简单:从原始数组中创建一个浅数组,其中元素是原始数组的implode
d“列”;然后对其应用array_unique(...)
;并且最后使用检测到的ID来过滤原始数组。
function arrayUniqueByRow(array $table = [], string $implodeSeparator)
{
$elementStrings = [];
foreach ($table as $row) {
// To avoid notices like "Array to string conversion".
$elementPreparedForImplode = array_map(
function ($field) {
$valueType = gettype($field);
$simpleTypes = ['boolean', 'integer', 'double', 'float', 'string', 'NULL'];
$field = in_array($valueType, $simpleTypes) ? $field : $valueType;
return $field;
}, $row
);
$elementStrings[] = implode($implodeSeparator, $elementPreparedForImplode);
}
$elementStringsUnique = array_unique($elementStrings);
$table = array_intersect_key($table, $elementStringsUnique);
return $table;
}
如果类型为object
,还可以改进比较,检测“列”值的类。
$implodeSeparator
应该或多或少复杂,z.B。 spl_object_hash($this)
。
第3。检测具有表(二维数组)的唯一标识符列的行
此解决方案依赖于第二个解决方案。现在,完整的“行”不需要是唯一的。如果一个“行”的所有相关的“字段”(第二维的元素)等于相应的“字段”,则两个“行”(第一维的元素)现在是相等的(具有相同键的元素。)
“相关”“字段”是“字段”(第二维的元素),它们具有键,等于传递的“标识符”的元素之一。
function arrayUniqueByMultipleIdentifiers(array $table, array $identifiers, string $implodeSeparator = null)
{
$arrayForMakingUniqueByRow = $removeArrayColumns($table, $identifiers, true);
$arrayUniqueByRow = $arrayUniqueByRow($arrayForMakingUniqueByRow, $implodeSeparator);
$arrayUniqueByMultipleIdentifiers = array_intersect_key($table, $arrayUniqueByRow);
return $arrayUniqueByMultipleIdentifiers;
}
function removeArrayColumns(array $table, array $columnNames, bool $isWhitelist = false)
{
foreach ($table as $rowKey => $row) {
if (is_array($row)) {
if ($isWhitelist) {
foreach ($row as $fieldName => $fieldValue) {
if (!in_array($fieldName, $columnNames)) {
unset($table[$rowKey][$fieldName]);
}
}
} else {
foreach ($row as $fieldName => $fieldValue) {
if (in_array($fieldName, $columnNames)) {
unset($table[$rowKey][$fieldName]);
}
}
}
}
}
return $table;
}
答案 8 :(得分:2)
扩展@ baba的答案,我喜欢,但创建了一个更复杂的三层深度多维(数组(数组(数组))):
$group = array();
foreach ( $array as $value ) {
$group[$value['id']][] = $value;
}
// output only data from id 96
foreach ($group as $key=>$value) { //outer loop
foreach ($value as $k=>$v){ //inner loop
if($key==96){ //if outer loop is equal to 96 (could be variable)
for ($i=0;$i<count($k);$i++){ //iterate over the inner loop
printf($key.' has a part no. of '.$v['part_no'].' and shipping no. of '.$v['shipping_no'].'<br>');
}
}
}
}
将输出:
96有一部分号码。的遗产和运输号码为212755-1
96有一部分号码。 dftgtryh和发货号码212755-1
答案 9 :(得分:2)
使用LINQ是很简单的,LINQ在PHP中用几个库实现,包括YaLinqo *。它允许对数组和对象执行类似SQL的查询。 groubBy
函数专为分组而设计,您只需指定要分组的字段:
$grouped_array = from($array)->groupBy('$v["id"]')->toArray();
其中'$v["id"]'
是此库支持的function ($v) { return $v["id"]; }
的简写。
结果与接受的答案完全相同,只需少量代码。
*由我开发
答案 10 :(得分:2)
$arr = array();
foreach($old_arr as $key => $item)
{
$arr[$item['id']][$key] = $item;
}
ksort($arr, SORT_NUMERIC);
答案 11 :(得分:1)
答案 12 :(得分:1)
$ arr =数据荒谬;
$ fldName =按列名分组;
function array_group_by( $arr, $fldName) {
$groups = array();
foreach ($arr as $rec) {
$groups[$rec[$fldName]] = $rec;
}
return $groups;
}
function object_group_by( $obj, $fldName) {
$groups = array();
foreach ($obj as $rec) {
$groups[$rec->$fldName] = $rec;
}
return $groups;
}
答案 13 :(得分:1)
function array_group_by($arr, array $keys) {
if (!is_array($arr)) {
trigger_error('array_group_by(): The first argument should be an array', E_USER_ERROR);
}
if (count($keys)==0) {
trigger_error('array_group_by(): The Second argument Array can not be empty', E_USER_ERROR);
}
// Load the new array, splitting by the target key
$grouped = [];
foreach ($arr as $value) {
$grouped[$value[$keys[0]]][] = $value;
}
// Recursively build a nested grouping if more parameters are supplied
// Each grouped array value is grouped according to the next sequential key
if (count($keys) > 1) {
foreach ($grouped as $key => $value) {
$parms = array_merge([$value], [array_slice($keys, 1,count($keys))]);
$grouped[$key] = call_user_func_array('array_group_by', $parms);
}
}
return $grouped;
}
答案 14 :(得分:1)
这应该组合一个关联数组 Ejm Group By Country
function getGroupedArray($array, $keyFieldsToGroup) {
$newArray = array();
foreach ($array as $record)
$newArray = getRecursiveArray($record, $keyFieldsToGroup, $newArray);
return $newArray;
}
function getRecursiveArray($itemArray, $keys, $newArray) {
if (count($keys) > 1)
$newArray[$itemArray[$keys[0]]] = getRecursiveArray($itemArray, array_splice($keys, 1), $newArray[$itemArray[$keys[0]]]);
else
$newArray[$itemArray[$keys[0]]][] = $itemArray;
return $newArray;
}
$countries = array(array('Country'=>'USA', 'State'=>'California'),
array('Country'=>'USA', 'State'=>'Alabama'),
array('Country'=>'BRA', 'State'=>'Sao Paulo'));
$grouped = getGroupedArray($countries, array('Country'));
答案 15 :(得分:0)
function groupeByPHP($array,$indexUnique,$assoGroup,$keepInOne){
$retour = array();
$id = $array[0][$indexUnique];
foreach ($keepInOne as $keep){
$retour[$id][$keep] = $array[0][$keep];
}
foreach ($assoGroup as $cle=>$arrayKey){
$arrayGrouped = array();
foreach ($array as $data){
if($data[$indexUnique] != $id){
$id = $data[$indexUnique];
foreach ($keepInOne as $keep){
$retour[$id][$keep] = $data[$keep];
}
}
foreach ($arrayKey as $val){
$arrayGrouped[$val] = $data[$val];
}
$retour[$id][$cle][] = $arrayGrouped;
$retour[$id][$cle] = array_unique($retour[$id][$cle],SORT_REGULAR);
}
}
return $retour;
}
尝试此功能
groupeByPHP($yourArray,'id',array('desc'=>array('part_no','packaging_type')),array('id','shipping_no'))
答案 16 :(得分:0)
按键将二维数组从头到尾分组的递归函数
输入:
$arr = array(
'0' => array(
'key0' => 'value0',
'key1' => 'value1',
'key2' => 'value02',
),
'2' => array(
'key0' => 'value0',
'key1' => 'value1',
'key2' => 'value12',
),
'3' => array(
'key0' => 'value0',
'key1' => 'value3',
'key2' => 'value22',
),
);
$keys = array('key0', 'key1', 'key2');
输出:
$arr = array(
'value0' => array(
'value1 => array(
'value02' => null,
'value12' => null,
),
'value3' => 'value22',
),
);
代码:
function array_group_by_keys(&$arr, $keys) {
if (count($arr) < 2){
$arr = array_shift($arr[0]);
return;
}
foreach ($arr as $k => $item) {
$fvalue = array_shift($item);
$arr[$fvalue][] = $item;
unset($arr[$k]);
}
array_shift($keys);
foreach ($arr as &$sub_arr) {
array_group_by_keys($sub_arr, $keys);
}
}
答案 17 :(得分:0)
我认为这在PHP 5.5及更高版本中效果更好
$IdVar = array_column($data, 'id');