Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing duplicate strings in Python list

I have a Python list and there is exactly one element which is repeated thrice. I want to replace them with unique element.

my_list = [,...,'future_use',...,'future_use',..'future_use',...]

Expected o/p:

[,...,'future_use1',...,'future_use2',..'future_use3',...]

I tried using list comprehension:

count = my_list.count("future_use")
for i in range(1, count+1):
    my_list = [item.replace("future_use","future_use%r" %i,i) for item in my_list]

However, I'm not getting desired output.Can someone point me to the correct procedure?

like image 971
Sumit Avatar asked Jan 04 '23 06:01

Sumit


2 Answers

You could use Counter and defaultdict from collections and count from itertools to make this a little shorter; whether it's clearer depends on how much time you've spent with Python. Patterns like this are used a lot, though, and are worth being familiar with..

(python 3.6 style here, using f-strings)

from collections import Counter, defaultdict
import itertools

seq = ["a", "future_use", "b", "b", "future_use", "c", "future_use"]

counts = Counter(seq)
suffix_counter = defaultdict(lambda: itertools.count(1))
seq2 = [elem if counts[elem] == 1 else elem + f'_{next(suffix_counter[elem])}'
        for elem in seq]

gives me

>>> seq2
['a', 'future_use_1', 'b_1', 'b_2', 'future_use_2', 'c', 'future_use_3']
like image 150
DSM Avatar answered Jan 14 '23 11:01

DSM


Here is the general approach:

my_list = ['foo', 'foo', 'whatever', 'whatever', 'nevermind', 'foo']

new_list = [] 
counts = {}

for el in my_list:
    temp_count = counts.get(el, 0) + 1
    counts[el] = temp_count 

    if temp_count == 1 and my_list.count(el) == 1:
        new_list.append(el)
    else:
        new_list.append(el + str(temp_count))

print(new_list) # ['foo1', 'foo2', 'whatever1', 'whatever2', 'nevermind', 'foo3']

Rather slow, but pretty straightforward.


UPD

Adapting the @DSM's great answer, this can be also implemented as follows:

my_list = ['foo', 'foo', 'whatever', 'whatever', 'nevermind', 'foo']

from collections import Counter

ranges = {k:[str(i + 1) for i in range(v)] for k,v in Counter(my_list).items()}
new_list = [el if ranges[el] == ['1'] else (el + ranges[el].pop(0)) for el in my_list]

print(new_list) # ['foo1', 'foo2', 'whatever1', 'whatever2', 'nevermind', 'foo3']
like image 21
MaximTitarenko Avatar answered Jan 14 '23 10:01

MaximTitarenko