0

I'm looking for something similar to this question, but in Python.

I have a list with repeated elements:

["Apple", "Orange", "Apple", "Pear", "Banana", "Apple", "Apple", "Orange"]

I'm looking for a list expression or a methodology that will give me:

["Apple 1", "Orange 1", "Apple 2", "Pear 1", "Banana 1", "Apple 3", "Apple 4", "Orange 2"]

Obviously, preserving order is very important.

martineau
  • 119,623
  • 25
  • 170
  • 301

3 Answers3

4

Option 1
collections.Counter

from collections import Counter

mapping = {k : iter(range(1, v + 1)) for k, v in Counter(lst).items()} 
lst2 = ['{} {}'.format(x, next(mapping[x])) for x in lst]

print(lst2)
['Apple 1', 'Orange 1', 'Apple 2', 'Pear 1', 'Banana 1', 'Apple 3', 'Apple 4', 'Orange 2']

Option 2
itertools.count

juan suggests the use of itertools.count, a great alternative to the above.

from itertools import count

mapping = {k : count(1) for k in set(lst)}   
lst2 = ['{} {}'.format(x, next(mapping[x])) for x in lst]

print(lst2)
['Apple 1', 'Orange 1', 'Apple 2', 'Pear 1', 'Banana 1', 'Apple 3', 'Apple 4', 'Orange 2']

The difference between this and the one above is in the manner in which mapping is defined.

cs95
  • 379,657
  • 97
  • 704
  • 746
  • you could use an `itertools.count` object instead, and avoid the use of `Counter`, so `mapping` would just be `{k:count() for e in x}` – juanpa.arrivillaga Sep 19 '17 at 20:10
  • @juanpa.arrivillaga Works fantastic! If you want to add it to your answer, let me know and I'll remove it from mine. – cs95 Sep 19 '17 at 20:31
  • I am wondering which one would be faster, have you done some benchmarking? – norok2 Sep 20 '17 at 06:14
  • @norok2 No, I haven't had the chance to do it, but I expect them to be about the same... – cs95 Sep 20 '17 at 06:16
1

The straightforward way seems obvious enough:

>>> from collections import Counter
>>> counts = Counter()
>>> x = ["Apple", "Orange", "Apple", "Pear", "Banana", "Apple", "Apple", "Orange"]
>>> new_x = []
>>> for item in x:
...     counts[item] += 1
...     new_x.append(f"{item}{counts[item]}")
...
>>> new_x
['Apple1', 'Orange1', 'Apple2', 'Pear1', 'Banana1', 'Apple3', 'Apple4', 'Orange2']
>>>
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • 1
    Note to readers: `f` strings work on python3.6 (?) and above. For older versions, use `str.format`. – cs95 Sep 19 '17 at 20:32
1
from collections import Counter

data = ["Apple", "Orange", "Apple", "Pear", "Banana", "Apple", "Apple", "Orange"]
a = Counter(data)

for i in range(len(data) - 1, -1, -1):
    index = str(a[data[i]])
    a[data[i]] -= 1
    data[i] += ' ' + index   

Now data is equal to ['Apple 1', 'Orange 1', 'Apple 2', 'Pear 1', 'Banana 1', 'Apple 3', 'Apple 4', 'Orange 2'].

This modifies the given list in-place.

ForceBru
  • 43,482
  • 10
  • 63
  • 98