Цикл Есод с разбивкой по категориям
Я пытаюсь просмотреть список товаров в деревушке, у каждого товара есть категория. Я хотел бы разбить вывод на группы по категориям со списком продуктов под заголовком каждой категории. Есть ли способ сделать это в Гамлете, просматривая мои продукты? То, что у меня сейчас есть, показывает заголовок для каждого продукта. Я думаю, что я мог бы пойти об этом все неправильно.
$if null products
<p>No products
$else
<div class="list-group menu">
$forall product <- products
<div class="list-group-item">
<h4 class="list-group-item-heading">#{categoryName $snd product}
<div class="list-group-item">
<div class="container-fluid">
<div class="col-md-12">
<p>#{productName $fst product} - #{productPrice $fst product}
И ниже немного кода, который получает продукты из базы данных типа [(Product Category)]
products <- runDB $ selectList [ProductName !=. ""] [LimitTo 10] >>= mapM (\qe@(Entity _ q) -> do
Just category <- get $ productCategory q
return (q, category))
1 ответ
Я думаю, что ответ заключается в том, чтобы ваш контроллер Yesod сгруппировал продукты по категориям для вас.
Например, вместо экспорта:
products :: [Product]
экспорт:
productGroups :: [ (Category, [Product]) ]
и тогда ваш код шаблона выглядит так:
$if null productGroups
<p>No products.
$else
<div ...>
$forall (category, products) <- productGroups
<h4>#{category}</h4>
$forall product <- products
<div>...render the product...</div>
Таким образом, товары появляются в группах в соответствии с их категорией.
Для создания товарных групп вы можете использовать что-то вроде:
import GHC.Exts (groupWith)
groupByCategory :: [Product] -> [ (Category, [Product]) ]
groupByCategory ps = [ (getCategory (head g), g) | g <- groupWith getCategory ]
where getCategory product = categoryName (snd product)
Предостережение: это непроверенный, не опробованный код.
Обновить
В ответ на ваш вопрос в комментариях, вот способ сгруппировать список пар по второй координате:
import Data.Ord (comparing)
import Data.List (sortBy, groupBy)
groupBySecond :: Ord b => [ (a,b) ] -> [ (b, [a]) ]
groupBySecond pairs =
let sorted = sortBy (comparing snd) pairs
groups = groupBy (\(a1,b1) (a2,b2) -> b1 == b2) sorted
result = [ (snd (head g), map fst g) | g <- groups ]
in result