Haskell:列表中的编号项

时间:2017-03-14 03:58:18

标签: list haskell numbers

我正在尝试根据相对于前一个元素的顺序对列表中的项目进行编号,例如" book"在下面的列表中。

[book 1, book 2, title 2.1, author 2.1, title 2.2, book 3, title 3.1, book 4, author 4.1]

我想:

zip [fst (head (zip[1..][x | x <- myList, x=="book"]))..][x | x <- myList, x=="title" || x=="author"]

&#34; title&#34;计数重新开始为1和&#34;作者&#34;在一本新的&#34;书&#34;满足了。 我可以轻松地为这些书编号,但我不知道如何根据书号对其他项目进行编号。

所以我尝试在列表理解中组合一个zip,如下所示:

 [(1,"title"),(2,"author"),(3,"title"),(4,"title"),(5,"author")]

但我得到的是:

http://query.yahooapis.com/v1/public/yql

结果是元组还是列表并不重要。

我非常感谢你的帮助。

谢谢, 奥马

2 个答案:

答案 0 :(得分:2)

您可以使用辅助功能来跟踪计数变量:

number xs = number' 0 0 xs
number' n m (x:xs) | x == "book" = (x,n+1,0) : number' (n+1) 0 xs
number' n m (x:xs) | otherwise = (x,n,m+1) : number' n (m+1) xs
number' _ _ [] = []

答案 1 :(得分:0)

有许多用于累积列表的函数。在这种情况下,我们想要map之类的东西,除了我们需要携带前面元素的信息。执行此操作的函数是scanl :: (s -> a -> s) -> s -> [a] -> [s]

你最好积累一对整数而不是浮点数。浮动是不精确的,所以你可能会得到一些你想要的东西。让我们说s = (Int, Int)并创建步骤函数。

step :: (Int, Int) -> String -> (Int, Int)
step (a, b) s@"book"   = (a + 1, 0    )
step (a, b) s@"title"  = (a    , b + 1)
step (a, b) s@"author" = (a    , b + 1)
step x      _          = x

当我们看到"book"时,我们将1添加到左侧整数,并将正整数设置为0。当我们看到"title""author"时,我们将1添加到正整数,并保持左整数相同。否则,我们将两个整数保持一致。您可以根据需要进行修改。

scanl step (0, 0) myList
= [(0,0),(1,0),(2,0),(2,1),(2,2),(2,3),(3,0),(3,1),(4,0),(4,1)]

我们需要做两件事。首先,scanl生成初始状态作为第一个元素,但我们不想要它。这可以通过taildrop 1轻松删除(tail是可以的,因为scanl始终会生成非空列表,但是很多人更愿意看到drop 1 )。其次,我们希望用适当的字符串扩充每个元组。

zipWith (\s (a, b) -> (s, a, b)) <*> drop 1 . scanl step (0, 0)

如果您不熟悉<*>,则(<*>) f g x = f x (g x)(在本例中)。我们也可以写:

\xs -> zipWith (\s (a, b) -> (s, a, b)) xs ((drop 1 . scanl step (0, 0)) xs)