帮助PHP循环

时间:2010-12-06 00:00:29

标签: php arrays loops

假设我有一个形式的多维数组:

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

4 个答案:

答案 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);

请注意,这里的递归示例非常低效,双循环是最快的。