函数将元组解压为两个列表Haskell
我正在寻找一个函数,它获取元组列表函数将元组解压为两个列表Haskell,haskell,Haskell,我正在寻找一个函数,它获取元组列表[(a,b)],并将其解压缩到[a]和[b]。我看过Hoogle,但我能找到的唯一函数是unzip,它接受一个元组并返回元组中的列表。有没有一个函数可以做到这一点?如果不是,是否应该使用解压,然后创建一个函数,返回[a]的第一个列表和[b]的第二个列表您编写了一个函数,返回[a]的第一个列表和[b]的第二个列表。嗯,unzip就是这样做的,将两个列表成对返回。在Haskell中,返回一对是返回两件东西最直接的方法 我想你认为你需要的不是解压,但你不需要。例如,假
[(a,b)]
,并将其解压缩到[a]
和[b]
。我看过Hoogle,但我能找到的唯一函数是unzip
,它接受一个元组并返回元组中的列表。有没有一个函数可以做到这一点?如果不是,是否应该使用解压
,然后创建一个函数,返回[a]
的第一个列表和[b]
的第二个列表您编写了一个函数,返回[a]
的第一个列表和[b]
的第二个列表。嗯,unzip
就是这样做的,将两个列表成对返回。在Haskell中,返回一对是返回两件东西最直接的方法
我想你认为你需要的不是解压
,但你不需要。例如,假设您有一个[(Int,String)]
,您所要做的就是将所有Int
s相乘以获得n
,将字符串连接起来以获得s
,然后返回s++“=”+++show n
。你可以这样做:
input=[(1,“x”),(2,“y”),(3,“z”)]
output=let(nums,strings)=解压输入——nums和strings是两个列表
n=产品nums
s=concat字符串
在s++“=”+++中显示n
解压::[(a,b)]->([a],[b])
确实返回两个列表[a]
和[b]
,它们只是包装在一对中,因为所有Haskell函数类型都只有一个输入和一个输出
为了提取结果,您可以将模式匹配与大小写一起使用
:
-- | Example input.
input :: [(Int, Char)]
input = [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D')]
或者,因为此模式是完整的(无可辩驳,忽略非终止),具有let
或where
绑定:
main = do
let
(fs, ss) = unzip input
print fs
print ss
如果您只需要第一个列表或第二个列表,可以分别提取它们:
main = do
let fs = map fst input
print fs
let ss = map snd input
print ss
但是,如果要同时使用map fst
和map snd
,则会遍历输入列表两次,因此unzip
更可取,因为它只遍历一次
使用元组是从一个函数返回多个结果的正常方式,当结果只有少数(2–3)时。如果不止这些,则最好使用记录类型,以便为字段指定清晰的名称
返回多个结果的另一种方法是连续传递样式(CPS),在本上下文中,这意味着将两个结果传递给用户指定的“回调”函数,而不是在元组中返回它们:
unzipCps
:: [(a, b)] -- ^ Input list
-> ([a] -> [b] -> c) -- ^ Output callback
-> c
unzipCps ((x, y) : rest) returnBoth
= unzipCps rest prependBoth
where
prependBoth xs ys = returnBoth (x : xs) (y : ys)
unzipCps [] returnBoth = returnBoth [] []
main = do
-- Equivalent to the original ‘unzip’.
let (fs, ss) = unzipCps input (,)
print fs
print ss
-- The result type (‘c’ in ‘unzipCps’)
-- can be anything, including an ‘IO’ action.
unzipCps input $ \ fs ss -> do
print fs
print ss
有时,当使用GADTs
/RankNTypes
时,这种风格是必要的,或者有助于实现性能优化,但是在这种情况下,使用它没有特别的优势,而且它有不同的性能特点。您认为您的函数类型是什么?unzip
正是您所需要的。你能解释一下为什么你认为它不合适吗?您可以编写一个函数,返回[a]
的第一个列表和[b]
的第二个列表。嗯,unzip
就是这样做的,将两个列表成对返回。如果不是成对的,您希望如何获得这两个列表?我想你认为你需要的不是解压
,但你不需要。也许给我们一个关于你试图达到的总体目标的线索会对你有所帮助。@Enlico“如果不是成对的话,如何……获得这两个列表?”foo xs k=let{(a,b)=unzip xs}。在k a b
@WillNess中,你不是还在使用(a,b)=unzip xs unzip xs?
main = do
let fs = map fst input
print fs
let ss = map snd input
print ss
firsts :: [(a, b)] -> [a]
firsts = map fst
seconds :: [(a, b)] -> [b]
seconds = map snd
main :: IO ()
main = do
let
fs = firsts input
ss = seconds input
print fs
print ss
unzipCps
:: [(a, b)] -- ^ Input list
-> ([a] -> [b] -> c) -- ^ Output callback
-> c
unzipCps ((x, y) : rest) returnBoth
= unzipCps rest prependBoth
where
prependBoth xs ys = returnBoth (x : xs) (y : ys)
unzipCps [] returnBoth = returnBoth [] []
main = do
-- Equivalent to the original ‘unzip’.
let (fs, ss) = unzipCps input (,)
print fs
print ss
-- The result type (‘c’ in ‘unzipCps’)
-- can be anything, including an ‘IO’ action.
unzipCps input $ \ fs ss -> do
print fs
print ss