Reputation: 107
I'm trying to write a function which accepts a list of chars and return a list of tuples composed of the chars that were repetitive in the list and how many times they repeated. For example: if I have a list such as: ["a", "a", "b", "b", "b", "c", "a", "a"]
It should return:
[('a', 2), ('b', 3), ('c', 1), ('a', 2)]
I wrote a code for this but the output I get is:
[('a', 2), ('b', 3), ('c', 1)]
Here is my code:
def comress(lst):
i = 0
counter = 0
new_list = []
while i < len(lst) -1:
if lst[i] == lst[i+1]:
counter += 1
i += 1
else:
counter += 1
tup = (lst[i], counter)
new_list.append(tup)
counter = 0
i += 1
return new_list
a = ["a", "a", "b", "b", "b", "c", "a", "a"]
print(comress(a))
I don't know what the problem is. I would like to hear your opinion. Thanks in advance.
Upvotes: 2
Views: 92
Reputation: 85582
This is probably the most pythonic solution that uses your counter logic:
def comress(lst):
counter = 1
new_list = []
for val1, val2 in zip(lst[:-1], lst[1:]):
if val1 == val2:
counter += 1
else:
new_list.append((val1, counter))
counter = 1
new_list.append((val2, counter))
return new_list
a = ["a", "a", "b", "b", "b", "c", "a", "a"]
print(comress(a))
Output:
[('a', 2), ('b', 3), ('c', 1), ('a', 2)]
Upvotes: 0
Reputation: 85582
You don't need to keep an extra counter, just increment the counter in the tuple if the value is the same as the previous one:
def compress(lst):
res = [(lst[0], 1)] # take first value
for val in lst[1:]: # go through the rest of the values
if val == res[-1][0]: # if the value is the same as the last one in res
res[-1] = (val, res[-1][-1] + 1) # increment the count
else: # otherwise
res.append((val, 1)) # add a new value-count pair
return res
print(compress(lst))
Output:
[('a', 2), ('b', 3), ('c', 1), ('a', 2)]
Upvotes: 2
Reputation: 17074
One liner with collections.Counter()
and itertools.groupby()
methods.
from itertools import groupby
from collections import Counter
l1 = ["a", "a", "b", "b", "b", "c", "a", "a"]
print [Counter(g).items()[0] for _, g in groupby(l1)]
Output:
[('a', 2), ('b', 3), ('c', 1), ('a', 2)]
Upvotes: 2
Reputation: 60024
You can try using itertools.groupby
:
from itertools import groupby
L = ["a", "a", "b", "b", "b", "c", "a", "a"]
newL = []
for k, g in groupby(L):
tempL = list(g)
newL.append((k, len(tempL)))
Upvotes: 1
Reputation: 10669
Your code does not insert into the list when it comes to the last items, if they are equal you don't insert them.
You need to check the last items as well, if they are equal so insert them as well, as in here:
lst= ["a", "a", "b", "b", "b", "c", "a", "a"]
def comress(lst):
i = 0
counter = 0
new_list = []
while i < len(lst) - 1:
if lst[i] == lst[i+1]:
counter += 1
i += 1
else:
counter += 1
tup = (lst[i], counter)
new_list.append(tup)
counter = 0
i += 1
if i + 1 == len(lst) and lst[i] == lst[i-1]:
counter +=1
tup = (lst[i], counter)
new_list.append(tup)
return new_list
a = ["a", "a", "b", "b", "b", "c", "a", "a"]
print(comress(a))
>>> [('a', 2), ('b', 3), ('c', 1), ('a', 2)]
Upvotes: 1
Reputation: 4820
Your code will only append to new_list
when the current character is different from the previous one. When the list traversal ends though, it ignores the last streak of characters.
Upvotes: 1