按类别细分的 Yesod 小村庄循环
Yesod hamlet loop broken down by categories
我试图遍历 hamlet 中的产品列表,每个产品都有一个类别。我想将输出分解为类别,每个类别标题下方都有一个产品列表。在遍历我的产品时,有没有办法在 hamlet 中执行此操作。我目前在下面显示的是每种产品的标题。我想我可能做错了。
$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))
我认为答案是让您的 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
我试图遍历 hamlet 中的产品列表,每个产品都有一个类别。我想将输出分解为类别,每个类别标题下方都有一个产品列表。在遍历我的产品时,有没有办法在 hamlet 中执行此操作。我目前在下面显示的是每种产品的标题。我想我可能做错了。
$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))
我认为答案是让您的 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