Группа php array

У меня есть следующий массив

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 для этого?

Если я сделаю это выше, я получу дубликат, как я могу избежать этого?

В приведенном выше примере id имеет 2 элемента, поэтому его необходимо находиться внутри id .

РЕДАКТИРУЙТЕ: ВСЕ РАБОТАЕТ ТЯЖЕЛО: НО ЕСТЬ ЛИ КАКИЕ-ЛИБО ПУТЬ, ЧТОБЫ ДОСТИГНУТЬ ОДНУ ИСКУССТВО?

Related of "Группа php array"

Существует не родной, просто используйте цикл.

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

В более функциональном стиле программирования вы можете использовать array_reduce

 $groupedById = array_reduce($data, function ($accumulator, $element) { if (!isset($accumulator[$element['id']])) { $accumulator[$element['id']] = []; } $accumulator[$element['id']][] = $element; return $accumulator; }, []); 

Расширяя ответ на @ 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

Это связано с LINQ, который реализован в PHP в нескольких библиотеках, включая YaLinqo *. Он позволяет выполнять SQL-запросы на массивы и объекты. Функция groubBy предназначена специально для группировки, вам просто нужно указать поле, в которое вы хотите группировать:

 $grouped_array = from($array)->groupBy('$v["id"]')->toArray(); 

Где '$v["id"]' является сокращением для function ($v) { return $v["id"]; } function ($v) { return $v["id"]; } который поддерживает эта библиотека.

Результат будет точно таким же, как в принятом ответе, с меньшим количеством кода.

* разработан мной

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. Обнаружение уникальных строк для таблицы (двухмерный массив)

Эта функция предназначена для фильтрации «строк». Если мы говорим, что двумерный массив является таблицей, то каждый его элемент представляет собой строку. Таким образом, мы можем удалить дублированные строки с помощью этой функции. Две строки (элементы первого измерения) равны, если все их столбцы (элементы второго измерения) равны. Для сравнения значений столбца применяется: Если значение имеет простой тип , само значение будет использоваться при сравнении; в противном случае его тип ( array , object , resource , unknown type ) будет использоваться.

Стратегия проста: сделать из исходного массива неглубоким массивом, где элементы будут implode d "столбцы" исходного массива; затем примените array_unique(...) на нем; и в качестве последнего используют обнаруженные идентификаторы для фильтрации исходного массива.

 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 должен быть более или менее сложным, 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; } с 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; } с 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; 

}