1

I have not long been learning python and after going through the basics have been going through some tasks I have found online.

For this one I'm to use a list of characters in this case the alphabet to count the amount of those characters in a sentence.

I have got to the point where it is counting something but cuts out on character c giving me a value of 30 when there is only 1 c in there and the return:

  File "/home/pi/main.py", line 17, in <module>
    if statementLower[l] == alphabet[m]:
IndexError: string index out of range

Code attached

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
statement = "This is my task I want to complete. But I am stuck!!!!!!"
statementLower = statement.lower()
m = 0
l=0
count = 0
print(statementLower)

for i in alphabet:
    frequency = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    #print("i for alphabet")
    #print("-" + i + "-")
    for k in statementLower:
        #print("k statement Lower")
        #print(k)
        if statementLower[l] == alphabet[m]:
            #print(count)
            count = count+1
            frequency[m] = count
            l+l+1
            continue
        else:
            #print("else continue loop")
            l=l+1
            continue
        
    if frequency[m] != 0:
        #print("frequency loop")
        print(str(alphabet[m]+ ":" + str(frequency[m])))
        m=m+1
        count = 0
        l=0
        continue

Can anyone give me any assistance in what I'm doing wrong I can see that I am constantly getting stuck in that count if statement but its not incrementing to the next index of the string even when I am increasing that value.

my only current returns are a:44 b:20 c:30 then the string index out of range

seb
  • 19
  • 1
  • @j1-lee Beginners tend not to be familiar with all available modules. Of course Counter is ideal for this but as a learning exercise it's good to do this sort of thing yourself – DarkKnight Sep 30 '22 at 17:05

4 Answers4

3

I've noticed two errors in your code:

  • You are only resetting the counter variables if the current frequency value is not 0, meaning that it will error out eventually after encountering a character that isn't present in the target string. Resetting these values outside of the if statement makes your code go beyond "c", but will still result in invalid values.
  • You have a l+l+1 statement in your code; probably a typo, and you meant l=l+1.

Correcting these errors result in your code working as intended. Below is your original source file (without the initializers at the top); I have left comments documenting what these errors are (and added some tips on how to make your code more "pythonic").

for i in alphabet:
    frequency = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    for k in statementLower:
        if statementLower[l] == alphabet[m]:
            count = count + 1 # Can be simplified to count += 1
            frequency[m] = count # You don't have to have the "count" variable at all; instead, you can simply use frequency[m]. That'll save you the hassle of keeping track of an extra variable.
            # If you want to stop using the "count" variable, simply replace the above two lines with "frequency[m] += 1". You can then delete all lines referencing "count".
            l+l+1 # This statement will do nothing; you probably meant the first "+" to be a "=".
            continue
        else:
            # These assignments can be moved outside the else-if; and, as this is the only statement in the else-if,
            # the else can be removed completely.
            l=l+1
            continue
        
    if frequency[m] != 0:
        print(str(alphabet[m]+ ":" + str(frequency[m])))
        # You are only resetting your counter variables if the current frequency value is not 0.
        # The reason why your code didn't execute correctly after "c" is because there are no
        # "d" characters in the string; so you're not updating m, count, and l after you encounter such a character.
        m=m+1
        count = 0
        l=0
        continue

Also, your script can be simplified to this:

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
statement = "This is my task I want to complete. But I am stuck!!!!!!"
statementLower = statement.lower()
m = 0
l=0
count = 0
print(statementLower)

frequency = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

# For each letter index of the array "alphabet"
for i in range(len(alphabet)):
    # For each character of the string "statementLower"
    for k in statementLower:
        # If the character is equal to the character under the alphabet index i...
        if k == alphabet[i]:
            # ...add 1 to the frequency under that index.
            frequency[i] += 1
    
# Print out the frequencies
for i in range(len(alphabet)):
    if frequency[i] != 0:
        print(str(alphabet[i]+ ": " + str(frequency[i])))
        # bonus: f-strings! they're cool, fancy, and are more pythonic! :3
        # print(f"{alphabet[i]}: {frequency[i]}")

Best of luck in your Python endeavors!

ascpixi
  • 529
  • 4
  • 13
  • 1
    Thank you for this is incredibly easy to understand. It's not easy to find info on some of these without them immediately suggesting the use of modules. which can help with a quick solution but not understanding. – seb Sep 30 '22 at 17:57
0

I've come up with this, similar to first answer:

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
statement = "This is my task I want to complete. But I am stuck!!!!!!"


statementLower = statement.lower()

print(statementLower)

setz = [i for i in statementLower if i in alphabet ] #list of char in statementLower if they are in alphabet
print(setz)

#freqs = [(item, setz.count(item)) for item in set(setz)] #freq as list, uses .count() method on set() of setz
                                                         
freqs = dict([(item, setz.count(item)) for item in set(setz)]) # freqs as dictionary, see above

print(freqs)

output:

this is my task i want to complete. but i am stuck!!!!!!
['t', 'h', 'i', 's', 'i', 's', 'm', 'y', 't', 'a', 's', 'k', 'i', 'w', 'a', 'n', 't', 't', 'o', 'c', 'o', 'm', 'p', 'l', 'e', 't', 'e', 'b', 'u', 't', 'i', 'a', 'm', 's', 't', 'u', 'c', 'k']
{'w': 1, 'm': 3, 'b': 1, 'n': 1, 'c': 2, 'a': 3, 'k': 2, 'h': 1, 'l': 1, 'u': 2, 'o': 2, 'e': 2, 'y': 1, 's': 4, 'i': 4, 'p': 1, 't': 7}

my bad that from Python 3.6 dictionary preserve inserting order while mine doesnt follow alphabet, see: Are dictionaries ordered in Python 3.6+?

pippo1980
  • 2,181
  • 3
  • 14
  • 30
0

As has already been said, collections.Counter is ideal for this. However, if you want to do this without importing anything, you could consider using a dictionary (which is essentially how Counter is implemented). The dictionary will be keyed on any letters in the range a-z found in the statement string.

statement = 'This is my task I want to complete. But I am stuck!!!!!!'

result = {}

for letter in statement.lower():
    if letter.isalpha():
        result[letter] = result.get(letter, 0) + 1

for key, value in sorted(result.items()):
    print(f'{key}={value}')

Output:

a=3
b=1
c=2
e=2
h=1
i=4
k=2
l=1
m=3
n=1
o=2
p=1
s=4
t=7
u=2
w=1
y=1
DarkKnight
  • 19,739
  • 3
  • 6
  • 22
-2

First option: use collections.Counter. As suggested by Steven Rumbalski:

frequency = collections.Counter(filter(str.isalpha, statement.lower()))

If you want a bit more work, then there is the str.count() method. Suggestion: let's make frequency a dict instead of a list

frequency = {}
for a in alphabet:
    frequency[a] = statementLower.count(a) 

If you want still more work, ok:

frequency = {a:0 for a in alphabet} #or use a defaultdict instead
for a in alphabet:
    for ch in statementLower:
        if a == ch:
            frequency[a] += 1
gimix
  • 3,431
  • 2
  • 5
  • 21
  • 1
    `collections.Counter` would be the ideal solution in this scenario, but please note that this is a beginner learning Python, so I would say it's better for them to do it the "slow" way to understand the language and its basic concepts better. – ascpixi Sep 30 '22 at 17:22
  • Or just `frequency = collections.Counter(filter(str.isalpha, statement.lower()))`, but that doesn't advance the OP's understanding of what's wrong with their code. – Steven Rumbalski Sep 30 '22 at 17:23
  • @ascpixi Their scenario isn't exactly clear, but quite likely using `statementLower.count` would be better than `Counter`. – Kelly Bundy Sep 30 '22 at 18:14
  • @KellyBundy: Running `statementLower.count` would have to be run on each letter meaning a full iteration for every character. – Steven Rumbalski Sep 30 '22 at 21:29
  • @StevenRumbalski Yes, but that's likely still faster and possibly shorter (depends on what exactly they want). – Kelly Bundy Sep 30 '22 at 21:47