列表中的Haskell组元素,并加入不同的相邻元素
group
在data.list
中可以将同一元素分组 输入:
import Data.List(group)
group "mississippi time"
输出:
["m","i","ss","i","ss","i","pp","i"," ","t","i","m","e"]
如何修改group
函数以将不同的相邻元素分组在一起?
期望:
["mi","ss","i","ss","i","pp","i time"]
下面是我错误的解决方案。
我尝试对相同的元素进行分组,然后将不同的元素分组。分组不同的元素时,我还检查每个元素的长度。由于groupsame
,因此单独留下不同的元素。
-- |
-- >>> groupSame "mississippi time"
-- ["m","i","ss","i","ss","i","pp","i"," ","t","i","m","e"]
groupSame :: String -> [String]
groupSame [] = []
groupSame (x:xs) = (x : takeWhile (== x) xs) : groupSame (dropWhile (== x) xs)
-- >>> groupDiff ["m","i","ss","i","ss","i","pp","i"," ","t","i","m","e"]
-- ["mi","ss","i","ss","i","pp","i time"]
groupDiff :: [String] -> [String]
groupDiff [] = []
groupDiff [x] = [x]
groupDiff (x:y:xs)
|length x > 1 && length y > 1 = x:y : groupDiff xs
|length x > 1 && length y ==1 = x: groupDiff (y:xs)
|length x ==1 && length y > 1 = x:y: groupDiff xs
|length x ==1 && length y ==1 = (x++y): groupDiff xs
预期输出高于groupdiff
签名。 但是我得到了:
["mi","ss","i","ss","i","pp","i"," t","im","e"]
The group
function in Data.List
can group the same element in a list
Input:
import Data.List(group)
group "mississippi time"
Output:
["m","i","ss","i","ss","i","pp","i"," ","t","i","m","e"]
How to modify the group
function to group the different adjacent elements together?
Expect:
["mi","ss","i","ss","i","pp","i time"]
Below is my WRONG solution.
I try to group the same elements and then group the different elements. When grouping different elements, I also check the length of each element. Since after groupSame
, different elements are left alone.
-- |
-- >>> groupSame "mississippi time"
-- ["m","i","ss","i","ss","i","pp","i"," ","t","i","m","e"]
groupSame :: String -> [String]
groupSame [] = []
groupSame (x:xs) = (x : takeWhile (== x) xs) : groupSame (dropWhile (== x) xs)
-- >>> groupDiff ["m","i","ss","i","ss","i","pp","i"," ","t","i","m","e"]
-- ["mi","ss","i","ss","i","pp","i time"]
groupDiff :: [String] -> [String]
groupDiff [] = []
groupDiff [x] = [x]
groupDiff (x:y:xs)
|length x > 1 && length y > 1 = x:y : groupDiff xs
|length x > 1 && length y ==1 = x: groupDiff (y:xs)
|length x ==1 && length y > 1 = x:y: groupDiff xs
|length x ==1 && length y ==1 = (x++y): groupDiff xs
The expected output is above the groupDiff
signature.
However I got:
["mi","ss","i","ss","i","pp","i"," t","im","e"]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
那呢?
我想可以以某种方式缩短lambda。
我猜
(== 1)。长度
可以命名issingleton
。而且,它可以用作
null。 tail
要保存一些括号,fwiw:随着更多播放,您甚至可以摆脱变量
x
和y
,并以无点的样式写入它,只要您为Pairs编写的
的替代方案,
但这可能不那么可读。
您也需要
导入data.list(groupby)
。其他人在评论中向您解释了为什么您的解决方案不起作用。
但是,我的观点是,首先,您不应该达到如此复杂的解决方案。
手工递归是一种功能强大的工具,但是对于如此简单的美味来说,递归太强大了。确实,您迷失了细节。
如果您知道自己只想以某种方式进行 group ,请与
group
和groupby
,group
,teach of伸出并查看如何将它们结合在一起以获得想要的东西。这就是我通过写下我想做的事情,
,然后从计划的关键部分中提取我需要的功能:
group
do do do do dogroupby
允许给定谓词以外的谓词,长度
可以计算长度,(== 1)用于检查一个数字是否为1
concat
仅此操作(对于任何列表,不仅是字符串,btw)MAP
。给定上述情况,我到了这里:
我知道
dotheygotogether
将使用(== 1)。长度
以某种方式。了解(== 1)并不是一个巨大的飞跃。长度
对于x
和y
的全部应为true:dotheyGotogeTher = all )
。ps: hoogle 是您的朋友。
What about this?
I guess the lambda can be shortened somehow.
I guess
(== 1) . length
could be namedisSingleton
.And, it could be implemented as
null . tail
to save some parenthesis, fwiw:With some more playing, you can even get rid of variables
x
andy
and write it in point-free style, provided you write an alternative ofall
for pairs,but this is likely less readable.
You need
import Data.List (groupBy)
too.Somebody else explained to you in a comment why your solution does not work.
My point, however, is that you shouldn't reach for such complicated solutions in the first place.
Hand-made recursion is a powerful tool, but for such a simple tast is just too much powerful; indeed, you get lost into details.
If you know that you just want to group things in some way, then reach out for functions that are for grouping, like
group
andgroupBy
, and see how you can combine them together to get what you want.That's how I crafted my solution (which, performance-wise, might be not optimal), by just writing down what I wanted to do,
and then extracting the functions I need from the key parts of my plan:
group
doesgroupBy
allows grouping given a predicate other than equality,length
can compute the length, and(== 1)
is for checking if a number is 1concat
does just that (for any list, not just strings, btw)map
on the list of groups.Given the above, I got here:
where I knew
doTheyGoTogether
would use(== 1) . length
somehow. Not a huge leap to understand that(== 1) . length
should be true for all ofx
andy
:doTheyGoTogether = all ((== 1) . length)
.P.S: Hoogle is your friend.