我想编写一个函数,根据满足给定属性p
的项目将列表拆分为子列表。我的问题是如何调用该函数。我将在Haskell中给出示例,但同样的问题会出现在F#或ML中。
split :: (a -> Bool) -> [a] -> [[a]] --- split lists into list of sublists
连接的子列表是原始列表:
concat (split p xss) == xs
每个子列表都满足initial_p_only p
属性,也就是说(A)子列表以满足p
的元素开头 - 因此不是空的,并且(B)没有其他元素满足{{ 1}}:
p
所以准确一点,
initial_p_only :: (a -> Bool) -> [a] -> Bool
initial_p_only p [] = False
initial_p_only p (x:xs) = p x && all (not . p) xs
如果原始列表中的第一个元素不满足all (initial_p_only p) (split p xss)
,则拆分失败。
此函数需要被称为p
以外的其他函数。 我该怎么称呼?
答案 0 :(得分:12)
我相信您所描述的功能来自list-grouping包中的breakBefore
。
Data.List.Grouping
:http://hackage.haskell.org/packages/archive/list-grouping/0.1.1/doc/html/Data-List-Grouping.html
ghci> breakBefore even [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6]
[[3,1],[4,1,5,9],[2],[6,5,3,5],[8,9,7,9,3],[2,3],[8],[4],[6],[2],[6]]
答案 1 :(得分:2)
我非常喜欢基于“休息”这个术语的名字,正如亚当斯所说的那样。该功能有很多可能的变种。这是我期望的(基于F#库中使用的命名)。
一个名为breakBefore
的函数将占用一个元素,之前它应该断开:
breakBefore :: Eq a => a -> [a] -> [[a]]
具有With
后缀的函数将采用某种函数直接指定何时中断。如果是brekaing,这是您想要的函数a -> Bool
:
breakBeforeWith :: (a -> Bool) -> [a] -> [[a]]
你还可以想象一个带有By
后缀的函数会带一个键选择器并在键发生变化时中断(有点像group by
,但你可以拥有具有相同密钥的多个组):
breakBeforeBy :: Eq k => (a -> k) -> [a] -> [[a]]
我承认名字有点长 - 也许唯一真正有用的功能是你想要的。但是,F#库似乎非常一致地使用这种模式(例如sort
,sortBy
采用密钥选择器,sortWith
采用比较器功能)。
也许有可能将这三种变体用于更多的列表处理函数(并且为这三种类型提供一些一致的命名模式是非常好的。)