Помогите с циклом PHP - PullRequest
       1

Помогите с циклом PHP

1 голос
/ 06 декабря 2010

Предположим, у меня есть многомерный массив вида:

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')
)

Массив имеет больше подмассивов, но это базовая форма-- Items in Sets.

Как мне пройти через этот массив, чтобы я мог отображать количество элементов в каждом наборе вместе со всеми элементами, например, так:

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 голосов
/ 06 декабря 2010

Правильно, все приведенные ниже примеры основаны на упорядоченном наборе, 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);

Обратите внимание, что рекурсивнаяпример здесь крайне неэффективен, двойной цикл, безусловно, самый быстрый.

0 голосов
/ 06 декабря 2010

Необходимость не распечатывать какие-либо предметы, пока мы не узнаем, сколько их в наборе, делает это трудным. В какой-то момент нам понадобится выполнить некоторую буферизацию или возврат. Однако, если мне разрешены внутренние циклы и наборы смежны в массиве «master», то с некоторыми взломами:

$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;
}
0 голосов
/ 06 декабря 2010

Как насчет этого:

$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;
0 голосов
/ 06 декабря 2010
<?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'];
    }
}
?>

Что-то вроде этого, я думаю?

РЕДАКТИРОВАТЬ: После того, как я опубликовал это, я увидел функции дисплея, которые были добавлены.Но вы поняли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...