[Haskell-beginners] Padding List with Zeros
Henry Olders
henry.olders at mcgill.ca
Thu Sep 16 12:32:00 EDT 2010
On 2010-09-15, at 15:12 , Daniel Fischer wrote:
> On Wednesday 15 September 2010 20:24:09, Hein Hundal wrote:
>> On Wed, 15 Sep 2010 16:23:49, Daniel Fischer wrote:
>>> On Wednesday 15 September 2010 15:15:49, Henry Olders wrote:
>>>> On 2010-09-14, at 19:35 , Lorenzo Isella wrote:
>>>>> Dear All,
>>>>> I still have to find my way with immutable lists and list
>>>>> comprehension. Consider the following lists
>>>>>
>>>>> A=[0,10,20,30,40,50]
>>>>> B=[0,10,50] (i.e. B is a subset of list A; list A is
>>>>> already ordered in increasing order and so is B).
>>>>> C=[2,1,-5] i.e. there is a corresponding element in C for every
>>>>> element in B.
>>>>>
>>>>> Now, I would like to define a new list D having length equal
>>>>> to the length of A. The elements of D in the position of the
>>>>> elements of A in common with B are equal to the corresponding
>>>>> entries in C, whereas the other ones are zero i.e.
>>>>> D=[2,1,0,0,0,-5]. How can I achieve that? The first thought
>>>>> that comes to my mind is to define a list of zeros which I
>>>>> would modify according to my needs, but that is not allowed...
>>
>> Yes, that is not allowed. First thing I thought of also.
>>
>>>>> Many thanks
>>>>>
>>>>> Lorenzo
>>>>
>>>> Being a real Haskell newby, I can figure out a one-line solution in
>>>> Python, but I don't know how to do something similar in Haskell, or
>>>> even if it's possible. Please correct me if I'm wrong, but there
>>>> does not seem to be a dictionary type in Haskell, and I am not aware
>>>> of how to specify an inline if...else inside a list comprehension. I
>>>> would really appreciate it if someone could show me how to do
>>>> something similar to this Python statement in Haskell.
>>>
>>> import Data.Maybe
>>>
>>>>>>> A=[0,10,20,30,40,50]
>>>>>>> B=[0,10,50]
>>>>>>> C=[2,1,-5]
>>>
>>> These have to be lowercase in Haskell, of course :)
>>>
>>>>>>> [dict(zip(B,C))[a] if a in B else 0 for a in A]
>>>
>>> map (fromMaybe 0 . (`lookup` zip b c)) a
>>>
>>> or, as a list comprehension,
>>>
>>> [fromMaybe 0 (lookup v dic) | let dic = zip b c, v <- a]
>>>
>>> Slightly more verbose than the Python.
>>>
>>> But this doesn't deal with multiple entries (istr that was
>>> mentioned previously in this thread), for
>>>
>>> a = [0, 10, 10, 20, 30 , 40, 50]
>>> b = [0, 10, 10, 50]
>>> c = [2, 1, 3, -5]
>>>
>>> neither would produce
>>>
>>> [2, 1, 3, 0, 0, 0, -5]
>>>
>>> which I believe would be the desired behavior.
>>>
>>>> [2, 1, 0, 0, 0, -5]
>>>>
>>>> Henry
>>
>> I love the map solution and the lookup solutions--very concise. Someday
>> perhaps those will occur to me when I look at these problems.
>>
>> Here is my (extremely) verbose beginner solution. I think this solution
>> is linear time and it returns the "desired behavior" in Daniel's post.
>>
>> -- indices v1 v2
>> -- find the elemIndex of v2's elements in v1
>> -- almost equivalent to (map (flip elemIndex v1) v2)
>> --
>> indices v1 v2 = indices' 0 v1 v2
>> indices' iOff (x:xs) (y:ys)
>>
>> | x < y = indices' (iOff+1) xs (y:ys)
>> | x ==y = iOff:(indices' (iOff+1) xs ys)
>> | x > y = error "indicies:: elem not found"
>>
>> indices' _ _ [] = []
>> indices' _ [] (y:ys) = error "indices:: elem not found"
>>
>>
>> -- makevec 0 indices values
>> -- returns a vector with values filled in at the indices given
>> --
>> makevec _ [] _ = []
>> makevec _ _ [] = error "makevec:: "
>> makevec iOffSet (i:is) (x:xs)
>>
>> | iOffSet < i = replicate (i-iOffSet) 0 ++ makevec i (i:is) (x:xs)
>> | iOffSet ==i = x:(makevec (iOffSet+1) is xs)
>> | iOffSet > i = error "makevec error"
>>
>> hisfunc :: [Integer] -> [Integer] -> [Integer] -> [Integer]
>> hisfunc a b c = let front = makevec 0 (indices a b) c
>> in front ++ replicate (length a - length front) 0
>>
>>
>> test1 = hisfunc a b c
>> test2 = hisfunc (a++[70, 90]) b c
>> test3 = hisfunc (a++[70, 90]) (b++[70]) (c++[-14])
>> test4 = hisfunc [0,10,10,20,30,40,50] [0,10,10,50] [2,1,3,-5]
>
> Somewhat simpler in one go:
>
> -- Preconditions:
> -- length bs == length cs
> -- as and bs are sorted
> -- bs is a sublist of as
> expand :: (Ord a, Num a) => [a] -> [a] -> [a] -> [a]
> expand as [] _ = map (const 0) as
> expand (a:as) bbs@(b:bs) ccs@(c:cs)
> | a < b = 0 : expand as bbs ccs
> | otherwise = c : expand as bs cs
> expand _ _ _ = []
My thanks to the various contributors to this discussion. Lots of food for thought!
Henry
More information about the Beginners
mailing list