Reputation: 401
For example if I have a list as follows:
[3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]
How can I remove the duplicate elements and represent the same element followed by the number of times it's repeating? Example Output:
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]
Where 3 is repeating 6 times... 1 repeating 6 times... and so on
Upvotes: 3
Views: 2840
Reputation: 107287
As an alternative answer you can just play with indices using a recursion function and iter
:
def refiner(li,new=[]):
it=iter(li[1:])
for i,j in enumerate(li[:-1],1):
curr=next(it)
if j!=curr :
if i>1:
new+=[j,i]
return refiner(li[i:],new)
elif i==len(li)-1:
new+=[j,curr]
return new
else:
new+=[j]
return refiner(li[i:],new)
elif i==len(li)-1:
new+=[j,i+1]
return new
return new
DEMO:
l=[3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]
print refiner(l)
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]
l=[7, 7, 3, 9, 3, 3, 100, 1, 5, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 7, 1]
print refiner(l)
[7, 2, 3, 9, 3, 2, 100, 1, 5, 1, 4, 200, 3, 3, 100, 1, 7, 1]
Upvotes: -1
Reputation: 180391
The itertools is the best solution but for a different take without imports we can use a dict:
od = {}
prev = None
out = []
for ele in l:
if ele != prev and prev in od:
out.extend((prev, od[prev])) if od[prev] > 1 else out.append(prev)
od[prev] = 0
od.setdefault(ele, 0)
od[ele] += 1
prev = ele
out.extend((ele, od[ele])) if od[ele] > 1 else out.append(ele)
print(out)
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]
Or in a function using a more efficient defaultdict
,it takes more memory to store data in a dict but it is probably a faster solution that using groupby:
def grp1(l):
od = defaultdict(int)
prev = None
out = []
for ele in l:
if ele != prev and prev in od:
out.extend((prev, od[prev])) if od[prev] > 1 else out.append(prev)
od[prev] = 0
od[ele] += 1
prev = ele
out.extend((ele, od[ele])) if od[ele] > 1 else out.append(ele)
return out
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]
Interestingly it is a nice amount faster, probably because we don't have to loop over every sublist to get the len :
In [33]: l = [choice(l) for _ in range(100000)]
In [34]: timeit grp1(l)
10 loops, best of 3: 23.9 ms per loop
In [35]: timeit list(solve(l))
10 loops, best of 3: 33.9 ms per loop
In [36]: list(solve(l)) == grp1(l)
Out[36]: True
Upvotes: 0
Reputation: 41
Alternative solution without using itertools would be:
my_list = [3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]
new_list = []
new_list.append(my_list[0]) #adding first element
count = 1 #variable for counting repeated elements
i = 1 #iterator through list
l = len(my_list)
while i < l:
while i < l and my_list[i] == my_list[i-1]:
count +=1
i+=1
if count > 1:
new_list.append(count)
count = 1 #returning to original default value
else:
new_list.append(my_list[i])
i+=1
print(new_list)
Upvotes: -1
Reputation: 250891
You can use itertools.groupby
with a generator function here:
>>> from itertools import groupby
>>> lst = [3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1]
>>> def solve(seq):
for k, g in groupby(seq):
length = sum(1 for _ in g)
if length > 1:
yield k
yield length
else:
yield k
...
>>> list(solve(lst))
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3]
Upvotes: 7