chh
chh

Reputation: 167

Decompress an array in Python

I need to decompress an array and I am not sure where to start.

Here is the input of the function

def main():
    # Test case for Decompress function
    B = [6, 2, 7, 1, 3, 5, 1, 9, 2, 0]
    A = Decompress(B)
    print(A)

I want this to come out

A = [2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 9, 0, 0]

If you can't see the pattern, B[1] is how many times B[2] shows up in A[], and then B[3] is how many times B[4] shows up in A[], and so on.

How do I write a function for this?

Upvotes: 0

Views: 1065

Answers (4)

nad2000
nad2000

Reputation: 4945

A slightly faster solution (with Python 2.7.3):

A=list(chain.from_iterable( [ B[i]*[B[i+1]] for i in xrange(0,len(B),2) ] ) )

>>> timeit.Timer(
        setup='B=[6,2,7,1,3,5,1,9,2,0];from itertools import chain',
        stmt='A=list(chain.from_iterable( [ B[i]*[B[i+1]] for i in xrange(0,len(B),2) ] ) )').timeit(100000)
0.22841787338256836

Comparing with:

>>> timeit.Timer(
        setup='B=[6,2,7,1,3,5,1,9,2,0];from itertools import chain',
        stmt='A=list(chain.from_iterable([v] * c for c, v in zip(*([iter(B)]*2))))').timeit(100000)
0.31104111671447754

Upvotes: 0

LtWorf
LtWorf

Reputation: 7608

def unencodeRLE(i):
    i = list(i) #Copies the list to a new list, so the original one is not changed.
    r = []

    while i:
        count = i.pop(0)
        n = i.pop(0)
        r+= [n for _ in xrange(count)]
    return r

Upvotes: 1

Ellioh
Ellioh

Reputation: 5340

One more one-liner:

def decompress(vl):
    return sum([vl[i] * [vl[i+1]] for i in xrange(0, len(vl), 2)], [])
  1. A list comprehension extracts and unpacks pairs (xrange(0, len(vl), 2) iterates through start indices of pairs, vl[i] is a number of repetitions, vl[i+1] is what to repeat).

  2. sum() joins the results together ([] is the initial value the unpacked lists are sequentially added to).

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1124748

Compact version with zip() and itertools.chain.from_iterable:

from itertools import chain

list(chain.from_iterable([v] * c for c, v in zip(*([iter(B)]*2))))

Demo:

>>> B = [6, 2, 7, 1, 3, 5, 1, 9, 2, 0]
>>> from itertools import chain
>>> list(chain.from_iterable([v] * c for c, v in zip(*([iter(B)]*2))))
[2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 9, 0, 0]

Breaking this down:

  • zip(*([iter(B)]*2))) pairs counts with values:

    >>> zip(*([iter(B)]*2))
    [(6, 2), (7, 1), (3, 5), (1, 9), (2, 0)]
    

    It is a fairly standard Python trick to get pairs out of a input iterable.

  • ([v] * c for c, v in zip(*([iter(B)]*2))) is a generator expression that takes the counts and values and produces lists with the value repeated count times:

    >>> next([v] * c for c, v in zip(*([iter(B)]*2)))
    [2, 2, 2, 2, 2, 2]
    
  • chain.from_iterable takes the various lists produced by the generator expression and lets you iterate over them as if they were one long list.

  • list() turns it all back to a list.

Upvotes: 3

Related Questions