У меня есть таблица базы данных, которая выглядит так:
uid | group | category 1 | group1 | cat1 2 | group1 | cat2 3 | group2 | cat3 4 | group2 | cat4 5 | group2 | cat5 6 | group3 | cat6 7 | group3 | cat7
Но мне нужны эти данные в массиве, который группирует категории по их group
.
Например, мой массив должен выглядеть так:
Array ( [group1] => Array ( [0] => Array ( [0] => 1 [1] => cat1 ) [1] => Array ( [0] => 2 [1] => cat2 ) ) [group2] => Array ( [0] => Array ( [0] => 3 [1] => cat3 ) [1] => Array ( [0] => 4 [1] => cat4 ) [2] => Array ( [0] => 5 [1] => cat5 ) ) [group3] => Array ( [0] => Array ( [0] => 6 [1] => cat6 ) [1] => Array ( [0] => 7 [1] => cat7 ) ) )
Я написал цикл foreach, который делает только это, но у меня есть проблема.
Моя проблема заключается в том, что она всегда не учитывает последнюю строку таблицы, и я не уверен, как ее исправить. На мой взгляд, логика диктует, что она всегда должна работать.
Я думал, что после цикла я могу просто добавить последнюю строку в новый массив, но я думаю, что это может вызвать проблемы, если последняя строка имеет другую группу, и я предпочел бы, чтобы решение было встроено в цикл foreach.
К сожалению, я здесь не понимаю. Как я могу исправить свой код, чтобы включить самую последнюю строку запроса к базе данных?
Мне также было бы интересно узнать, какие улучшения я могу внести в свой текущий код, но это может быть лучшим вопросом для codereview.
Моя петля:
$pass = []; foreach($stmt as $key => $value) { if(empty($currentGroup)) $currentGroup = $value['group']; if(empty($temp)) $temp = []; if($currentGroup != $value['group'] || $key+1 == count($stmt)) { $pass[$currentGroup] = $temp; $currentGroup = $value['group']; $temp = []; $temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']]; } else { $temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']]; } }
Это должно сделать следующее:
<?php //Create an array to store our grouped rows $grouped = array(); //Loop over all rows returned by the $stmt that has been executed. //You could probably remove the key from here, it's not needed it seems. //The keys within the $value array will match the names of the columns in //the database, foreach($stmt as $key => $value){ //As we're storing by the group value from the row we first want to //check if our grouped array contains a key for the group of the row //being processed. If it does not, create an empty array within the //grouped data for this group. if(!array_key_exists($value['group'], $grouped)){ $grouped[$value['group']] = array(); } //Knowing we will always have an array element for the rows group //we can blindly append the values for this row to the grouped //container using its values. //'[] =' is just short hand append. $grouped[$value['group']][] = array( $value['uid'], $value['category'] ); }
Надеюсь, это поможет!
Для дальнейшего будущего доказательства этого цикла вы можете изменить сгруппированное значение, добавив следующее:
<?php //Setting the whole row (minus the group) rather than just the uid //and category explicitly allows this code to work without modification //as the datatable changes, ie. new columns. Assuming that is the 'group' //column remains present unset($value['group']); $grouped[$value['group']][] = $value;
с<?php //Setting the whole row (minus the group) rather than just the uid //and category explicitly allows this code to work without modification //as the datatable changes, ie. new columns. Assuming that is the 'group' //column remains present unset($value['group']); $grouped[$value['group']][] = $value;
Теперь можно получить доступ к данным с объединенным содержимым, используя следующее:
<?php //Acceess data via column name not array index, yay! echo $grouped['group1']['uid']
Я снова нуждался в этом, поэтому создал функцию, основанную на ответе @ JParkinson1991 .
Я помещаю это здесь для документации и, возможно, помогаю будущим читателям.
function groupArray($arr, $group, $preserveSubArrays = false, $preserveGroupKey = false) { $temp = array(); foreach($arr as $key => $value) { $groupValue = $value[$group]; if(!$preserveGroupKey) { unset($arr[$key][$group]); } if(!array_key_exists($groupValue, $temp)) { $temp[$groupValue] = array(); } if(!$preserveSubArrays){ $data = count($arr[$key]) == 1? array_pop($arr[$key]) : $arr[$key]; } else { $data = $arr[$key]; } $temp[$groupValue][] = $data; } return $temp; }
сfunction groupArray($arr, $group, $preserveSubArrays = false, $preserveGroupKey = false) { $temp = array(); foreach($arr as $key => $value) { $groupValue = $value[$group]; if(!$preserveGroupKey) { unset($arr[$key][$group]); } if(!array_key_exists($groupValue, $temp)) { $temp[$groupValue] = array(); } if(!$preserveSubArrays){ $data = count($arr[$key]) == 1? array_pop($arr[$key]) : $arr[$key]; } else { $data = $arr[$key]; } $temp[$groupValue][] = $data; } return $temp; }
function groupArray($arr, $group, $preserveGroupKey = false, $preserveSubArrays = false)
Эта функция принимает от 2 до 4 параметров.
Первый параметр – это сам массив, второй параметр – это ключ, который вы хотите сгруппировать, а третий (необязательный) параметр – это логическое значение, которое сообщает функции, если вы хотите сохранить групповой ключ в вспомогательных массивах.
$temp = array(); foreach($arr as $key => $value) { $groupValue = $value[$group]; if(!$preserveGroupKey) { unset($arr[$key][$group]); } if(!array_key_exists($groupValue, $temp)) { $temp[$groupValue] = array(); } $temp[$groupValue][] = $arr[$key]; }
с$temp = array(); foreach($arr as $key => $value) { $groupValue = $value[$group]; if(!$preserveGroupKey) { unset($arr[$key][$group]); } if(!array_key_exists($groupValue, $temp)) { $temp[$groupValue] = array(); } $temp[$groupValue][] = $arr[$key]; }
Во-первых, мы создаем временный массив с именем $temp
Затем мы перебираем массив, захватив ключ (который должен быть строкой или int), и значение (которое должно быть массивом).
Мы устанавливаем $groupValue
независимо от того, какое значение имеет $groupValue
вами $group
, например, «группа» в приведенном ниже примере.
$arr = [ 0 => [ "group" => "group1", "name" => "Bob", ], 1 => [ "group" => "group1", "name" => "Randy", ], 2 => [ "group" => "group1", "name" => "Susan", ], 3 => [ "group" => "group2", "name" => "Larry", ], 4 => [ "group" => "group2", "name" => "David", ], 5 => [ "group" => "group3", "name" => "Perry", ], ];
Затем мы проверяем, хотим ли мы $preserveGroupKey
. Если это логическое значение ложно (и по умолчанию), ключ будет удален, оставив несколько подмассивов только с ключевым словом «имя».
Теперь мы проверяем, существует ли $groupValue
в нашем массиве $temp
, если это не так, мы создаем его.
Затем мы добавляем к $temp[$groupValue]
любые значения текущей строки. Из приведенного выше примера мы получим:
Array ( [group1] => Array ( [0] => Bob [1] => Randy [2] => Susan ) [group2] => Array ( [0] => Larry [1] => David ) [group3] => Array ( [0] => Perry ) )
Или, если третий параметр установлен в true, вы получите:
Array ( [group1] => Array ( [0] => Array ( [name] => Bob ) [1] => Array ( [name] => Randy ) [2] => Array ( [name] => Susan ) ) [group2] => Array ( [0] => Array ( [name] => Larry ) [1] => Array ( [name] => David ) ) [group3] => Array ( [0] => Array ( [name] => Perry ) ) )