列表中的Haskell组元素,并加入不同的相邻元素

发布于 2025-02-05 17:26:17 字数 1337 浏览 0 评论 0原文

groupdata.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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陪我终i 2025-02-12 17:26:17

那呢?

 map concat $ groupBy (\x y -> all ((== 1) . length) [x, y]) $ group "mississippi time"

我想可以以某种方式缩短lambda。

我猜(== 1)。长度可以命名issingleton

而且,它可以用作null。 tail要保存一些括号,fwiw:

 map concat $ groupBy (\x y -> all (null . tail) [x, y]) $ group "mississippi time"

随着更多播放,您甚至可以摆脱变量xy,并以无点的样式写入它,只要您为Pairs编写的替代方案,

all' p (a, b) = p a && p b
map concat $ groupBy (curry $ all' (null . tail)) $ group "mississippi time"

但这可能不那么可读。


您也需要导入data.list(groupby)


其他人在评论中向您解释了为什么您的解决方案不起作用。

但是,我的观点是,首先,您不应该达到如此复杂的解决方案。

手工递归是一种功能强大的工具,但是对于如此简单的美味来说,递归太强大了。确实,您迷失了细节。

如果您知道自己只想以某种方式进行 group ,请与groupgroupbygroup,teach of伸出并查看如何将它们结合在一起以获得想要的东西。

这就是我通过写下我想做的事情,

  • 按平等(从而获得不同长度的字符串)
  • 组成的相邻字符串的相邻字符串1,
  • 这就是我制定解决方案的方式(在性能方面,可能不是最佳)。将每个组中的字符串串联

,然后从计划的关键部分中提取我需要的功能:

  • ake fiake yemality :这就是group do do do do do
  • em> group strings具有长度1 :groupby允许给定谓词以外的谓词,长度可以计算长度,(== 1)用于检查一个数字是否为1
  • constenate strings concat仅此操作(对于任何列表,不仅是字符串,btw)
  • :这意味着我必须在组列表上MAP

给定上述情况,我到了这里:

 map concat $ groupBy (\x y -> doTheyGoTogether) $ group "mississippi time"

我知道dotheygotogether将使用(== 1)。长度以某种方式。了解(== 1)并不是一个巨大的飞跃。长度对于 xy的全部应为true:dotheyGotogeTher = all )


ps: hoogle 是您的朋友。

What about this?

 map concat $ groupBy (\x y -> all ((== 1) . length) [x, y]) $ group "mississippi time"

I guess the lambda can be shortened somehow.

I guess (== 1) . length could be named isSingleton.

And, it could be implemented as null . tail to save some parenthesis, fwiw:

 map concat $ groupBy (\x y -> all (null . tail) [x, y]) $ group "mississippi time"

With some more playing, you can even get rid of variables x and y and write it in point-free style, provided you write an alternative of all for pairs,

all' p (a, b) = p a && p b
map concat $ groupBy (curry $ all' (null . tail)) $ group "mississippi time"

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 and groupBy, 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,

  • group letters by equality (thus obtaining strings of different lengths)
  • group together the adjacent strings that have length 1
  • concatenate the strings in each of the groups

and then extracting the functions I need from the key parts of my plan:

  • group by equality: that's what group does
  • group strings that have length 1: groupBy allows grouping given a predicate other than equality, length can compute the length, and (== 1) is for checking if a number is 1
  • concatenate the strings: concat does just that (for any list, not just strings, btw)
  • in each of the groups: that means I have to map on the list of groups.

Given the above, I got here:

 map concat $ groupBy (\x y -> doTheyGoTogether) $ group "mississippi time"

where I knew doTheyGoTogether would use (== 1) . length somehow. Not a huge leap to understand that (== 1) . length should be true for all of x and y: doTheyGoTogether = all ((== 1) . length).


P.S: Hoogle is your friend.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文