ctine132
ctine132

Reputation: 13

Run-Length Encoding Output for Python

These are the rules for what I need to perform a run-length encoding assignment:

  1. A standalone character will be unchanged. E.g "a" → ["a"].
  2. A run of a character, c, repeated N times will be compressed to ["c", "c", N]. E.g. "bbbb" → ['b', 'b', 4].

This is what my goal output would look like "aaaabbcccd" → ['a', 'a', 4, 'b', 'b', 2, 'c', 'c', 3, 'd'] which works the way I want it to work. However, this is the output from "abcd" → ['a', 'a', 1, 'b', 'b', 1, 'c', 'c', 1, d] and I'm looking for an output like this "abcd" → ['a', 'b', 'c', 'd']

string = "aaaabbcccd"

def encode(string):
    counter = 1
    result = ""
    previousLetter = string[0]
    if len(string)==1:
      return string[0]

    for i in range(1,len(string),1):
        if not string[i] == previousLetter:
            result += string[i-1] + string[i-1] + str(counter) 
            previousLetter = string[i]
            counter = 1
        else:
            counter += 1

        if i == len(string)-1:
                result += string[i]

    return result

result = encode(string)
print(result)

I know it has to do with this line: result += string[i-1] + string[i-1] + str(counter) so I was thinking about giving certain conditions for the number of times the character showed up but it no longer works when combined into the code. Perhaps there is something I can change in the first code to solve the problem without doing this extra code part but I'm not currently aware of?

if str(counter) == 1:
    result += string[i]
if str(counter) == 2:    
    result += string[i] + string[i] 
else:
    result += string[i] + string[i] + str(counter)

Upvotes: 1

Views: 1248

Answers (3)

LevB
LevB

Reputation: 953

You can use zip to offset the string by one, making your loop simpler.

st = "aaaabbcccd"

li = []
i=0
for c1,c2 in zip(st,st[1:]):
    i+=1
    if c1 != c2:
        li += [c1,c1,i]
        i=0

li += [c2]   
print(li)

Output:

['a', 'a', 4, 'b', 'b', 2, 'c', 'c', 3, 'd']   

Upvotes: 0

sahinakkaya
sahinakkaya

Reputation: 6056

If you have Python3.8, you can do it with one line thanks to walrus operator:

Python 3.8.1 (default, Jan  8 2020, 14:26:07)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from itertools import groupby, chain
>>> string = "aaaabbcccd"
>>> encoded = [*chain(*[[k, k, length] if (length := len([*g])) > 1 else [k] for k, g in groupby(string)])]
>>> print(encoded)
['a', 'a', 4, 'b', 'b', 2, 'c', 'c', 3, 'd']

Upvotes: 1

Tom Karzes
Tom Karzes

Reputation: 24052

This should do what you want:

def encode(string):
    string_len = len(string)
    i = 0
    result = []
    while i < string_len:
        count = 1
        c = string[i]
        i += 1
        while i < string_len and string[i] == c:
            count += 1
            i += 1
        if count == 1:
            result.append(c)
        else:
            result += [c, c, count]
    return result

It computes the run length for each new character, then adds the appropriate entry to the result list depending on whether the length is 1 vs. greater than 1.

Upvotes: 1

Related Questions