假设我有一个形式的多维数组:
array
(
array('Set_ID' => 1, 'Item_ID' => 17, 'Item_Name' = 'Whatever'),
array('Set_ID' => 1, 'Item_ID' => 18, 'Item_Name' = 'Blah'),
array('Set_ID' => 2, 'Item_ID' => 19, 'Item_Name' = 'Yo')
)
数组有更多的子数组,但这是基本形式 - 集合中的项目。
如何遍历此数组,以便我可以回显每个集合中的项目数以及所有项目,如下所示:
Set 1 has 2 Items: 17: Whatever and 18: Blah
Set 2 has 1 Items: 19: Yo
我知道这可以通过两个循环完成 - 一个用于构建数组,另一个用于循环遍历该数组。但是,我只想用一个循环来完成这一切。
在你的回答中,你应该假设有两个显示功能
display_set($id, $count) //echo's "Set $id has $count Items"
display_item($id, $name) //echo's "$id: $name"
更新:忘记提及数据按Set_ID排序,因为它来自SQL
答案 0 :(得分:0)
<?php
$sets = array();
foreach ($items as $item)
{
if (!array_key_exists($item['Set_ID'], $sets))
{
$sets[$item['Set_ID']] = array();
}
$sets[$item['Set_ID']][] = $item;
}
foreach ($sets as $setID => $items)
{
echo 'Set ' . $setID . ' has ' . count($items) . ' Items: ';
foreach ($items as $item)
{
echo $item['Item_ID'] . ' ' . $item['Item_Name'];
}
}
?>
我猜是这样的吗?
修改强> 我发布后,我看到显示功能添加。但你明白了。
答案 1 :(得分:0)
在我们知道装置中有多少物品之前,不打印任何物品的需要使这很困难。在某些时候,我们需要做一些缓冲,或者回溯。但是,如果我允许内部循环,并且集合在“主”数组中是连续的,那么就会有一些黑客攻击:
$set = 0;
$items;
foreach ($arr as $a) {
if ($a['Set_ID'] != $set) {
if ($set != 0) {
display_set($set, count($items));
foreach ($items as $i)
display_item($i)
}
$set = $a['Set_ID'];
$items = array();
}
$items[] = $a;
}
答案 2 :(得分:0)
这个怎么样:
$previous_set = false;
$items = '';
$item_count = 0;
foreach ($rows as $row)
{
if ($row['Set_ID'] != $previous_set)
{
if ($previous_set)
{
echo display_set($row['Set_ID'], $item_count);
echo $items;
}
$previous_class = $row['Set_ID'];
$item_count = 0;
$items = '';
}
$items .= display_item($row['Item_ID'], $row['Title']);
$item_count++;
}
echo display_set($row['Set_ID'], $item_count);
echo $items;
答案 3 :(得分:0)
是的,以下所有示例都依赖于有序集合,OP表示它最初是按顺序排序的,但如果需要,排序函数可以是:
// Sort set in to order
usort($displaySet,
create_function('$a,$b',
'return ($a['Set_ID'] == $b['Set_ID']
? ($a['Set_ID'] == $b['Item_ID']
? 0
: ($a['Item_ID'] < $b['Item_ID']
? -1
: 1))
: ($a['Set_ID'] < $b['Set_ID'] ? -1 : 1));'));
使用单个循环的直接示例:
// Initialise for the first set
$cSetID = $displaySet[0]['Set_ID'];
$cSetEntries = array();
foreach ($displaySet as $cItem) {
if ($cSetID !== $cItem['Set_ID']) {
// A new set has been seen, display old set
display_set($cSetID, count($cSetEntries));
echo ": " . implode(" and ", $cSetEntries) . "\n";
$cSetID = $cItem['Set_ID'];
$cSetEntries = array();
}
// Store item display for later
ob_start();
display_item($cItem['Item_ID'], $cItem['Item_Name');
$cSetEntries[] = ob_get_clean();
}
// Perform last set display
display_set($cSetID, count($cSetEntries));
echo ": " . implode(" and ", $cSetEntries) . "\n";
使用递归函数可能是这样的:
// Define recursive display function
function displayItemList($itemList) {
if (!empty($itemList)) {
$cItem = array_shift($itemList);
display_item($cItem['Item_ID'], $cItem['Item_Name');
if (!empty($itemList)) {
echo " and ";
}
}
displayItemList($itemList);
}
// Initialise for the first set
$cSetID = $displaySet[0]['Set_ID'];
$cSetEntries = array();
foreach ($displaySet as $cItem) {
if ($cSetID !== $cItem['Set_ID']) {
// A new set has been seen, display old set
display_set($cSetID, count($cSetEntries));
echo ": ";
displayItemList($cSetEntries);
echo "\n";
$cSetID = $cItem['Set_ID'];
$cSetEntries = array();
}
// Store item for later
$cSetEntries[] = $cItem;
}
// Perform last set display
display_set($cSetID, count($cSetEntries));
echo ": ";
displayItemList($cSetEntries);
echo "\n";
有趣的是,它可以是一个单一的递归函数:
function displaySetList($setList, $itemList = NULL) {
// First call, start process
if ($itemList === NULL) {
$itemList = array(array_shift($setList));
displaySetList($setList, $itemList);
return;
}
// Check for display item list mode
if ($setList === false) {
// Output first entry in the list
$cItem = array_shift($itemList);
display_item($cItem['Item_ID'], $cItem['Item_Name']);
if (!empty($itemList)) {
// Output the next
echo " and ";
displaySetList(false, $itemList);
} else {
echo "\n";
}
return;
}
if (empty($setList) || $setList[0]['Set_ID'] != $itemList[0]['Set_ID']) {
// New Set detected, output set
display_set($itemList[0]['Set_ID'], count($itemList));
echo ": ";
displaySetList(false, $itemList);
$itemList = array();
}
// Add next item and carry on
$itemList[] = array_shift($setList);
displaySetList($setList, $itemList);
}
// Execute the function
displaySetList($displaySet);
请注意,这里的递归示例非常低效,双循环是最快的。