5

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?

6 Answers 6

6

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']
Sign up to request clarification or add additional context in comments.

Comments

2

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']

1 Comment

for counting the appearances you can also use counter from itertools
1

You can try this one:

myList = ['future_use','future_use','future_use']

def makeUnique(myList, word):

    counter = 1

    for i in range(0,len(myList)):
        if myList[i] == word:
            myList[i] = word + str(counter)
            counter = counter + 1

makeUnique(myList, 'future_use')
print(myList)

The result is:

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

You can use it for every string element on a list.

Comments

0

Try this:

i = 0
for j, item in enumerate(my_list):
    if item == "future_use":
        my_list[j] = "future_use" + str(i)
        i += 1

4 Comments

i has to be initialized.
perhaps it should be for for i, item in enumerate(my_list):
@ismailsunni Nope.
@Brad Solomon this is exactly what Vasilis G. did. Same idea but generak.
0

Maybe using a generator here is a bit overkill but its a useful technique to know if you use list comprehensions and generators.

def gen(count):
    for i in range(count):
        yield i+1

my_list = ['mpla', 'future_use','mpla','future_use','future_use','mpla']
count = my_list.count("future_use")
idx = gen(count)
for i in range(count):
    my_list = [item if item!='future_use' 
               else 'future_use' + str(next(idx)) for item in my_list]

print(my_list)

Comments

0

Don't think about more memory efficient, faster, comprehensive and native method.

my_list = ['foo', 'bar', 'foo', 'foobar', 'bar', 'foo', 'foo', 'bar', 'foobar']
keywords = {}
for i, item in enumerate(my_list):
    if item in keywords:
        my_list[i] = item + str(keywords[item])
        keywords[item] += 1
    else:
        keywords[item] = 1
        my_list[i] = item + '1'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.