Search code examples
pythonlistmatrixencodingpython-itertools

How to do run-length encoding without creating sublists?


Thanking you for your help, I'd like to know how to make a function that does run-length encoding of a list, but doesn't create sublists. The reason is that each list represents a row of a two-dimensional list. In this way when I go to decode everything I will be able to do it line by line, having kept the lines of the original list. If possible, modify the code that I enclose, as it does a run-length encoding by writing the numbers of the repeated values, not writing the numbers of the values that are present only once.

from itertools import groupby
def modified_encode(alist):
        def ctr_ele(el):
            if len(el)>1:
                return [len(el), el[0]]
            else:
                return el[0]
        return [ctr_ele(list(group)) for key, group in groupby(alist)]

I'll explain. Here is an example using the function posted here:


wall = 'wall'
concrete = 'concrete'
>>> map=[wall, wall, concrete, concrete]
>>> modified_encode(map)
[[2, 'wall'], [2, 'concrete']]

The result I would like instead is this:

[2, 'wall', 2, 'concrete']

Solution

  • You could always return list - even for single item [ el[0] ] - and then you can use fact that you can add lists:

    [2,'wall'] + [2,'concrete'] + ['single'] gives [2,'wall',2,'concrete','single']

    You may even use sum(..., []) for this.

    from itertools import groupby
    
    def modified_encode(alist):
        def ctr_ele(el):
            if len(el)>1:
                return [len(el), el[0]]
            else:
                return [ el[0] ]   # <--- return list with single element
        
        result = (ctr_ele(list(group)) for key, group in groupby(alist))
        flatten = sum(result , [])  # <--- add all lists to `[]`
    
        return flatten
    
    data = ['wall', 'wall', 'concrete', 'concrete', 'single']
    
    modified_encode(data)
    

    Result:

    [2, 'wall', 2, 'concrete', 'single']
    

    EDIT:

    Or you could write it in different way - without ctr_ele - and use append()

    from itertools import groupby
    
    def modified_encode(alist):
        result = []
        
        for key, group in groupby(alist):
            el = list(group)
            if len(el) > 1:
                result.append(len(el))
            result.append(el[0])
            
        return result
    
    data = ['wall', 'wall', 'concrete', 'concrete', 'single']
    
    modified_encode(data)