4

I want to add numbers to list of strings so I can keep count of number of items.

Assume I have a list like this:

list = ['a', 'b', 'A', 'b', 'a', 'C', 'D', 'd']

I want to assign a number to each string irrespective of capital or small letters, Here's the output I'm looking for,

list = ['a_1', 'b_1', 'A_2', 'b_2', 'a_3', 'C_1', 'D_1', 'd_2']

This is what I've tried but I'm not getting the correct output

list = [j+f'_{i}' for i, j in enumerate(lst, 1)]
7
  • 3
    What is not working with your approach? Commented Jul 21, 2019 at 19:09
  • 2
    And where is your approach? Also don't use list since it's a python reserved name Commented Jul 21, 2019 at 19:09
  • I was only able to get this output: [a_1, b_2, a_3, b_4, a_5, c_6, D_7, d_8] Commented Jul 21, 2019 at 19:10
  • 1
    Add that code to the question? Commented Jul 21, 2019 at 19:11
  • So you're looking for a solution where a = A ? Commented Jul 21, 2019 at 19:12

4 Answers 4

4

You can keep track of how many times you have seen a number in a dictionary, and update the count whenever you see the letter, and use the last count to append to the character.

from collections import defaultdict

def label(lst):

    dct = defaultdict(int)
    output = []

    #Iterate through the list
    for item in lst:

        char = item.lower()
        #Update dictionary
        dct[char] += 1

        #Create the list of characters with count appended
        output.append(f'{item}_{dct[char]}')

    return output

print(label(['a', 'b', 'A', 'b', 'a', 'C', 'D', 'd']))

The output will be

['a_1', 'b_1', 'A_2', 'b_2', 'a_3', 'C_1', 'D_1', 'd_2']

Also don't use list as a variable name, since it's a reserved python builtin name.

Sign up to request clarification or add additional context in comments.

Comments

3

You can keep track of the counts using a dictionary:

newlist = []
counts = {}
for element in oldlist:
    if element.casefold() in counts:
        counts[element.casefold()] += 1
    else:
        counts[element.casefold()] = 1
    newlist.append(f'{element}_{counts[element.casefold()]}')

1 Comment

Tip: if you use counts = defaultdict(int), you could just increment the counter and don't need to write the if-else-statement (see answer of Devesh for example)
2

You can use a Counter for this to keep track of the number of times the item has been added, like:

from collections import Counter

def labelize(iterable):
    c = Counter()
    for item in iterable:
        sc = item.casefold()
        c[sc] += 1
        yield '{}_{}'.format(item, c[sc])

We can then label with:

>>> list(labelize(['a', 'b', 'A', 'b', 'a', 'C', 'D', 'd']))
['a_1', 'b_1', 'A_2', 'b_2', 'a_3', 'C_1', 'D_1', 'd_2']

We can generalize the above by using an arbitrary mapping function, like:

def labelize(iterable, key=lambda x: x):
    c = Counter()
    for item in iterable:
        ci = key(item)
        c[ci] += 1
        yield '{}_{}'.format(item, c[ci])

The equivalent here would be:

>>> list(labelize(['a', 'b', 'A', 'b', 'a', 'C', 'D', 'd'], str.casefold))
['a_1', 'b_1', 'A_2', 'b_2', 'a_3', 'C_1', 'D_1', 'd_2']

Note: please do not use str.lower or str.upper for case matching. Certain cultures have specific rules for case matching. For example in German, the eszett ß [wiki] has as uppercase 'SS', by using .tolower(), the two would be different). The str.casefold [Python-doc] is designed to map strings to a value that can be used for case-insensitive matching. See for more information 3.13 Default Case Algorithms of the Unicode 9 standard.

Comments

0

Here is another way:

original = ['a', 'b', 'A', 'b', 'a', 'C', 'D', 'd']

lowered_reversed = [i.lower() for i in original][::-1]

for i in range(len(lowered_reversed)):
    count = lowered_reversed.count(lowered_reversed[i])
    lowered_reversed[i] = lowered_reversed[i] + "_" + str(count)

new_list = lowered_reversed[::-1]

for i in range(len(original)):
    if original[i].isupper():
        new_list[i] = new_list[i].upper()

print(new_list)

Output:

['a_1', 'b_1', 'A_2', 'b_2', 'a_3', 'C_1', 'D_1', 'd_2']

4 Comments

will be better if second loop will be also on range. you even called the variable i which is usually for indices
Ok, I am changing.
looks better no? but why you changed to list1? should be original
By the way, yes, it looks better. ^^

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.