左边填写一个Haskell列表

时间:2015-03-19 19:13:46

标签: list haskell pad

如果我想右键填充Haskell整数列表,我可以执行以下操作:

rpad m xs = take m $ xs ++ repeat 0

没有必要得到列表的长度。我认为这将是非常有效的。

是否有类似的方式我可以def lpad,填充左边的列表,而不会产生计算长度等的费用?

5 个答案:

答案 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