如果我想右键填充Haskell整数列表,我可以执行以下操作:
rpad m xs = take m $ xs ++ repeat 0
没有必要得到列表的长度。我认为这将是非常有效的。
是否有类似的方式我可以def lpad
,填充左边的列表,而不会产生计算长度等的费用?
答案 0 :(得分:6)
首先值得一提的是,不要过分担心性能的细节。此代码不太可能位于代码的20%中,占用了80%的运行时间。
说到这里,表演在哪里真的很重要,在这里?如果m
很小而length xs
是巨大的或无限的,那么这很重要。我的意思是,如果m
很大(如同rpad
一样,那么获得良好的性能也会很好,如果您只处理列表中的第一个k
项,那么k
适用于某些k << m
),但当然问题描述要求您可能m
工作以查看最高结果。 (如果您提供了无限列表,则需要查看m
项,以便知道是否为第一个元素返回0
。)
在这种情况下,您确实想要填充take m xs
而不是xs
。这就是整个伎俩:
lpad m xs = replicate (m - length ys) 0 ++ ys
where ys = take m xs
答案 1 :(得分:5)
右边填充只需要检查输入列表(:
或[]
)中的第一个构造函数,以便生成第一个元素输出列表。这是一个流媒体操作(可以使用foldr
完成)。
左边填充需要检查整个输入列表,以便生成输出列表的第一个元素。也就是说,第一个元素是否为0
取决于列表的尾部(假设它不以0
开头)。这不能以流方式完成。对于第一个元素,O(min(m,length))是最好的。
另外,请注意,因为填充功能会在m
之后丢弃元素,如果您的输入列表长于此值。这可能是不需要的 - 有时定义填充,以便它只能添加元素,而不会删除。
答案 2 :(得分:0)
这是一组(未经尝试但正在编译的)填充/修饰函数(Unlicence d):
padL :: a -> Int -> [a] -> [a]
padL p s l
| length l >= s = l
| otherwise = replicate (s - length l) p ++ l
{-# INLINABLE padL #-}
padR :: a -> Int -> [a] -> [a]
padR p s l = take s $ l ++ repeat p
{-# INLINABLE padR #-}
trimL :: Int -> [a] -> [a]
trimL s l
| length l <= s = l
| otherwise = drop (length l - s) l
{-# INLINABLE trimL #-}
trimR :: Int -> [a] -> [a]
trimR = take
{-# INLINE trimR #-}
resizeL :: a -> Int -> [a] -> [a]
resizeL p s l
| length l == s = l
| length l < s = padL p s l
| otherwise = trimL s l
{-# INLINABLE resizeL #-}
resizeR :: a -> Int -> [a] -> [a]
resizeR p s l
| length l == s = l
| length l < s = padR p s l
| otherwise = trimR s l
{-# INLINABLE resizeR #-}
答案 3 :(得分:0)
这里是Unlicence d,(未经编译,但正在编译),可能是最佳术语填充/修剪功能集:
padL :: a -> Int -> [a] -> [a]
padL p s l
| length l >= s = l
| otherwise = replicate (s - length l) p ++ l
{-# INLINABLE padL #-}
padR :: a -> Int -> [a] -> [a]
padR p s l = take s $ l ++ repeat p
{-# INLINABLE padR #-}
trimL :: Int -> [a] -> [a]
trimL s l
| length l <= s = l
| otherwise = drop (length l - s) l
{-# INLINABLE trimL #-}
trimR :: Int -> [a] -> [a]
trimR = take
{-# INLINE trimR #-}
resizeL :: a -> Int -> [a] -> [a]
resizeL p s l
| length l == s = l
| length l < s = replicate (s - length l) p ++ l
| otherwise = drop (length l - s) l
{-# INLINABLE resizeL #-}
resizeR :: a -> Int -> [a] -> [a]
resizeR p s l
| length l == s = l
| length l < s = take s $ l ++ repeat p
| otherwise = take s l
{-# INLINABLE resizeR #-}
答案 4 :(得分:0)
@所罗门乌科
为什么在 length
中调用 padL
两次(其他人也是如此)?怎么样
padL :: a -> Int -> [a] -> [a]
padL p s l
| length' >= s = l
| otherwise = replicate (s - length') p ++ l
where length' = length l