对列表中的元素 [英] Pairs of elements from list

查看:109
本文介绍了对列表中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 [1,2,3,4] 转换为 [[1 2] [2 3] [3 4]] [(1 2)(2 3)(3 4)] 。在clojure中,我有(partition 2 1 [1,2,3,4])。我如何在Haskell中做到这一点?我怀疑标准api中有这样的功能,但我找不到它。 解决方案

标准技巧是 zip 列表中有它自己的 tail

 >让xs = [1,2,3,4] in zip xs(tail xs)
[(1,2),(2,3),(3,4)]

要了解它的工作原理,请直观地列出列表及其尾部。

  xs = 1:2:3:4:[] 
tail xs = 2:3:4:[ ]

并注意 zip

有两个更为细微的原因,它总是做正确的事情:




  • zip 当任何一个列表用完元素时停止。这是有道理的,因为我们不能在最后有一个不完整的对,它也确保我们不会从单个元素列表中获得对。

  • xs 为空,可能会发现 tail xs 抛出异常。但是,因为 zip
    首先检查它的第一个参数,当它看到它是空列表时,第二个参数
    永远不会被评估。 >


以上所有内容也适用于 zipWith ,所以无论您何时使用相同的方法需要将函数成对应用于相邻元素。



对于像Clojure的分区这样的通用解决方案,标准库。但是,您可以尝试如下所示:

  partition':: Int  - > Int  - > [a]  - > [[a]] 
分区'大小偏移
|大小< = 0 =错误分区:大小必须为正值
|偏移量< = 0 =错误分区:偏移量必须为正值
|否则=循环
其中
loop :: [a] - > [[a]]
loop xs = case split大小xs
- 如果第二部分是空的,我们就结束了。但我们可能
- 已经比我们要求的少,因此检查。
(ys,[]) - >如果长度ys ==大小,则[ys] else []
(ys,_) - > ys:loop(drop offset xs)


I want to convert [1,2,3,4] to [[1 2] [2 3] [3 4]] or [(1 2) (2 3) (3 4)]. In clojure I have (partition 2 1 [1,2,3,4]). How can I do it in haskell? I suspect there is such function in standard api but I can't find it.

解决方案

The standard trick for this is to zip the list with it's own tail:

> let xs = [1,2,3,4] in zip xs (tail xs)
[(1,2),(2,3),(3,4)]

To see why this works, line up the list and its tail visually.

      xs = 1 : 2 : 3 : 4 : []
 tail xs = 2 : 3 : 4 : []

and note that zip is making a tuple out of each column.

There are two more subtle reasons why this always does the right thing:

  • zip stops when either list runs out of elements. That makes sense here since we can't have an "incomplete pair" at the end and it also ensures that we get no pairs from a single element list.
  • When xs is empty, one might expect tail xs to throw an exception. However, because zip checks its first argument first, when it sees that it's the empty list, the second argument is never evaluated.

Everything above also holds true for zipWith, so you can use the same method whenever you need to apply a function pairwise to adjacent elements.

For a generic solution like Clojure's partition, there is nothing in the standard libraries. However, you can try something like this:

partition' :: Int -> Int -> [a] -> [[a]]
partition' size offset
  | size <= 0   = error "partition': size must be positive"
  | offset <= 0 = error "partition': offset must be positive"
  | otherwise   = loop
  where
    loop :: [a] -> [[a]]
    loop xs = case splitAt size xs of
                -- If the second part is empty, we're at the end. But we might
                -- have gotten less than we asked for, hence the check.
                (ys, []) -> if length ys == size then [ys] else []
                (ys, _ ) -> ys : loop (drop offset xs)

这篇关于对列表中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆