Haskell << loop >>

XHo*_*erX 2 sorting indexing haskell loops list

随着getIndex xs y我希望第一个子表的索引,xs其长度大于y.

输出是:

[[],[4],[4,3],[3,5,3],[3,5,5,6,1]]
aufgabe6: <<loop>>
Run Code Online (Sandbox Code Playgroud)

为什么getIndex不起作用?

import Data.List

-- Die Sortierfunktion --
myCompare a b
    | length a < length b = LT
    | otherwise = GT

sortList :: [[a]] -> [[a]]
sortList x = sortBy myCompare x

-- Die Indexfunktion --
getIndex :: [[a]] -> Int -> Int
getIndex [] y = 0
getIndex (x:xs) y
    | length x <= y = 1 + getIndex xs y
    | otherwise = 0
    where (x:xs) = sortList (x:xs)

main = do
    print (sortList [[4],[3,5,3],[4,3],[3,5,5,6,1],[]])
    print (getIndex [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2)
Run Code Online (Sandbox Code Playgroud)

And*_*ewC 8

让它终止

问题出在这种情况下

getIndex (x:xs) y
    | length x <= y = 1 + getIndex xs y
    | otherwise = 0
    where (x:xs) = sortList (x:xs)
Run Code Online (Sandbox Code Playgroud)

你很困惑哪个(x:xs)是哪个.你应该这样做

getIndex zs y
    | length x <= y = 1 + getIndex xs y
    | otherwise = 0
    where (x:xs) = sortList zs
Run Code Online (Sandbox Code Playgroud)

Main> main
[[],[4],[4,3],[3,5,3],[3,5,5,6,1]]
3
*Main> getIndex [[],[2],[4,5]] 1
2
*Main> getIndex [[],[2],[4,5]] 5
3
Run Code Online (Sandbox Code Playgroud)

这为您提供了至少y在排序列表中的第一个长度列表的编号,它实际上回答了问题" y原始中有多少列表的长度最多?"

我们怎样才能找到其他事实?

如果您想要原始列表中的位置,您可以使用zip以下位置标记条目及其位置:

*Main> zip [1..] [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
[(1,[4]),(2,[3,5,3]),(3,[4,3]),(4,[3,5,5,6,1]),(5,[])]
Run Code Online (Sandbox Code Playgroud)

让我们做一个实用功能来处理那些:

hasLength likeThis (_,xs) = likeThis (length xs)
Run Code Online (Sandbox Code Playgroud)

我们可以像这样使用它:

*Main> hasLength (==4) (1,[1,2,3,4])
True
*Main> filter (hasLength (>=2)) (zip [1..] ["","yo","hi there","?"])
[(2,"yo"),(3,"hi there")]
Run Code Online (Sandbox Code Playgroud)

这意味着现在可以轻松编写一个函数,该函数为您提供长度超过的第一个列表的索引y:

whichIsLongerThan xss y = 
    case filter (hasLength (>y)) (zip [1..] xss) of
         [] -> error "nothing long enough" -- change this to 0 or (length xss + 1) if you prefer
         (x:xs) -> fst x
Run Code Online (Sandbox Code Playgroud)

这给了我们

*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2
2
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 3
4
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 0
1
Run Code Online (Sandbox Code Playgroud)

短?

但我们可以做类似的技巧:

whichIsShorterThan xss y = 
    case filter (hasLength (<y)) (zip [1..] xss) of
         [] -> error "nothing short enough" -- change this to 0 or (length xss + 1) if you prefer
         (x:xs) -> fst x
Run Code Online (Sandbox Code Playgroud)

所以你得到了

*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2
1
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 1
5
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 0
*** Exception: nothing short enough
Run Code Online (Sandbox Code Playgroud)

一般性

让我们在那里拉出共同主题:

whichLength :: (Int -> Bool) -> [[a]] -> Int
whichLength likeThis xss = 
    case filter (hasLength likeThis) (zip [1..] xss) of
         [] -> error "nothing found" -- change this to 0 or (length xss + 1) if you prefer
         (x:xs) -> fst x
Run Code Online (Sandbox Code Playgroud)

所以我们可以做到

*Main> whichLength (==5) [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 
4
*Main> whichLength (>2) [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 
2
Run Code Online (Sandbox Code Playgroud)

  • 非常好的和彻底的答案.我很高兴知道思考过程而不仅仅是解决方案. (2认同)