KWunsch
KWunsch

Reputation: 73

How can I get rid of Assertion Error in Python?

I am currently upping my Python-game and have a task, to create a function, that checks for non-repeating characters in a sequence: Below is my solution.

   def find_first_non_repeated_char(sequence: str):
        characters = [el for el in sequence.lower()]
        my_dict = {el:characters.count(el) for el in characters if characters.count(el) == 1}
    
        if bool(my_dict) == False or my_dict.values() == 1:
          return None
        else:
          return list(my_dict)[0]

Upon calling this in my IDE I get it working everytime. However, the testing algo, probably used by Entwicklerheld.de seems to throw the following error:

Traceback (most recent call last):
  File "/data/task-data/alphabet/tests.py", line 49, in test_random
    f"Expected '{result}', but was '{find_first_non_repeated_char(random_string)}' in '{random_string}'")
AssertionError: 'a' != 'A'
- a
+ A
 : Expected 'A', but was 'a' in 'A'

The letter obviously changes with every run, but the core message remains the same. What am I doing wrong? :-D I haven't seen this before ...

The task begins as follows:

Given is the sequence EntwicklerHeld. You need to find the first character that is in the given string, but is in it only once. Capital letters count equal as small letters, but you have to return the letter of the input sequence. For the string EntwicklerHeld your function should return 'n'.

Thus, when I leave out the lower()-function I cannot get the first target, because the code then evaluates to "E", but "n" should be the one!

All the best, K

Upvotes: 1

Views: 6608

Answers (3)

Joffan
Joffan

Reputation: 1480

The error message is a bit mysterious, so check your instructions for input and output, but your method is also quite complicated. It would a good use of the Counter class from collections.

from collections import Counter
def find_first_non_repeated_char(sequence: str):
    used = Counter(sequence.lower())
    for el in sequence:
        if used[el.lower()] == 1:
            return el
    return None

Upvotes: 0

Srinivas Gunti
Srinivas Gunti

Reputation: 36

  1. prepare my_dict by iterating over the original sequence
  2. count using a normalized case. (lower)
    def find_first_non_repeated_char(sequence: str):
        characters = sequence.lower()
        my_dict = {el: characters.count(el.lower()) for el in sequence if characters.count(el.lower()) == 1}
        if bool(my_dict) == False or my_dict.values() == 1:
          return None
        else:
          return list(my_dict)[0]

Upvotes: 0

DeGo
DeGo

Reputation: 791

EDIT : The case of the characters are not taken into account for the evaluation. You can try a method like this :

seq = "EntwicklerHeld"
seq = seq.lower()
my_dict = {el:seq.count(el) for el in seq} 
print([s for s in seq if my_dict[s] == 1][0])

Now back to issues with your original code : The way you have created my_dict is correct, but you are not using it properly. You should iterate over the original sequence of characters and return the first character present in my_dict as the order of characters is relevant.

  1. bool(my_dict) == False : I do not understand this.
  2. my_dict.values() == 1 : mydict.values() will result in a list and comparison will result as false everytime.

ORIGINAL : You are changing all the characters to lower case in the line

characters = [el for el in sequence.lower()]

That seems unnecessary.

Upvotes: 1

Related Questions