PHP数组组
我有以下数组
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
分组数组? 有没有任何原生的PHPfunction可以做到这一点?
如果我foreach
上面那么我会得到一个重复的,我怎样才能避免呢?
在上面的例子中id
有2个项目,所以它需要在id
里面。
编辑:一切工作都很好:但是有什么办法可以实现一个前进?
没有本地的,只是使用循环。
$result = array(); foreach ($arr as $data) { $id = $data['id']; if (isset($result[$id])) { $result[$id][] = $data; } else { $result[$id] = array($data); } }
您可以尝试以下方法:
$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)
我只是一起扔在一起,灵感来自.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" } } }
我也需要这样的function。 我创build了这个,你通过哪个列你想分组:
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; }
for($i = 0 ; $i < count($arr) ; $i++ ) { $tmpArr[$arr[$i]['id']] = $arr[$i]['id']; } $vmpArr = array_keys($tmpArr); print_r($vmpArr);
这array_group_by函数实现你正在寻找的东西:
$grouped = array_group_by($arr, 'id');
它甚至支持多级分组:
$grouped = array_group_by($arr, 'id', 'part_no');
扩展@ baba的答案,我喜欢,但是创build了一个更复杂的三维深度多维(数组(arrays(数组))):
$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
LINQ是很简单的,在PHP中,包括YaLinqo *在内的多个库中实现。 它允许在数组和对象上执行类似于SQL的查询。 groubBy
函数是专门为分组而devise的,您只需要指定要分组的字段:
$grouped_array = from($array)->groupBy('$v["id"]')->toArray();
其中'$v["id"]'
是function ($v) { return $v["id"]; }
的缩写function ($v) { return $v["id"]; }
function ($v) { return $v["id"]; }
这个库支持。
结果将会与接受的答案完全一样,只需less量代码。
*由我开发
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.检测表(二维数组)的唯一行
此function用于过滤“行”。 如果我们说,一个二维数组是一个表,那么它的每个元素就是一行。 所以,我们可以用这个函数删除重复的行。 如果所有列(第二维的元素)相等,则两行(第一维的元素)是相等的。 对于“列”值的比较适用:如果值是简单types ,则值本身将用于比较; 否则将使用它的types( array
, object
, resource
, unknown type
)。
策略很简单:从原始数组中创build一个浅层数组,其中元素是原数组的内部“列”; 然后在其上应用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; }
如果types是object
,也可以改进比较,检测“列”值的类。
$implodeSeparator
应该或多或less复杂, spl_object_hash($this)
。
3.检测具有唯一标识符列的行(二维数组)
这个解决scheme依赖于第二个。 现在完整的“行”不需要是唯一的。 如果一个“行”的所有相关的 “字段”(第二维的元素)等于相应的“字段”(具有相同的键的元素),则两个“行”(第一维的元素)是相等的。
“相关的”“字段”是“字段”(第二维的元素),其具有键,其等于传递的“标识符”的元素之一。
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; }
$arr = array(); foreach($old_arr as $key => $item) { $arr[$item['id']][$key] = $item; } ksort($arr, SORT_NUMERIC);
这应该组合一个关联数组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'));
检查来自Nspl的 索引函数:
use function \nspl\a\indexed; $grouped = indexed($data, 'id');
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;
}
在更多的函数式编程风格中,可以使用array_reduce
$groupedById = array_reduce($data, function ($accumulator, $element) { if (!isset($accumulator[$element['id']])) { $accumulator[$element['id']] = []; } $accumulator[$element['id']][] = $element; return $accumulator; }, []);