Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.0k views
in Technique[技术] by (71.8m points)

python - Why am I presented with an IndexError and what ways can I make this code more succinct

so I'm struggling to complete a coding challenge in CodeWars, and I received an IndexError on CodeWars. When I run the code on PyCharm, the output is fine.

Coding Prompt

def alphabet_position(sentence):
    alphabet_cap = ["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"]
    alphabet_low = ["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"]

    sentence_list = list(sentence)

    # remove any non-letters from sentence
    i = 0
    while i < len(sentence_list):
        if sentence_list[i].isalpha() == False:
            sentence_list.remove(sentence_list[i])
        i += 1

# I had to create a specific remove(" ") because for some reason the "'" would be turned into a " " instead of being removed?
    i = 0
    while i < len(sentence_list):
        if sentence_list[i] == " ":
            sentence_list.remove(" ")
        i += 1

    # finding position of alphabet
    alpha_index = []
    k = 0
    j = 0
    while k < len(sentence_list):
        if sentence_list[k] == alphabet_low[j] or sentence_list[k] == alphabet_cap[j]:
            alpha_index.append(str((alphabet_low.index(alphabet_low[j])) + 1))
            j = 0
            k += 1
        else:
            j += 1

    sentence_index = " ".join(alpha_index)

    return sentence_index

Error message

Sample Tests:

from random import randint
test.assert_equals(alphabet_position("The sunset sets at twelve o' clock."), "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11")
test.assert_equals(alphabet_position("The narwhal bacons at midnight."), "20 8 5 14 1 18 23 8 1 12 2 1 3 15 14 19 1 20 13 9 4 14 9 7 8 20")

number_test = ""
for item in range(10):
    number_test += str(randint(1, 9))
test.assert_equals(alphabet_position(number_test), "")```

Any help would be appreciated!

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I can't really replicate the IndexError, but I can help you out with the compactness of your code. The quickest way I can think of for getting the job done is something like this:

import re # for the regular expression

def alphabet_position(sentence):

    # regular expression to filter out everything that is not a letter
    regex = re.compile('[^a-zA-Z]')

    # removing everything that doesn't match the regex
    sentence = regex.sub('', sentence)

    alpha_index = []
    for char in sentence.upper():
        # ord() returns the ASCII code,
        # we subtract by 64 to get the alphabetical index,
        # then we convert the integer to string
        # because the final result needs to be a string

        alpha_index.append(str(ord(char) - 64))
    
    return " ".join(alpha_index)

An explanation of what is going on:

  1. We don't need to store into two lists all the possible characters we need. We can just use a regular expression to remove everything that is not an alphabetical character: [^a-zA-Z].
  2. There's no need to iterate 3 times over the string: the regex takes care of the filtering, then we can use a single iteration over every character to find out their index in the alphabet. To do this, first we convert everything to uppercase with sentence.upper(), then we check the ASCII value of the current character and we subtract 64. This is done because the ASCII values follow the alphabetical order, and the first character, A, has value 65. Take a look at the table.

If you don't know how to use regular expressions, another way to solve the problem is

def alphabet_position(sentence):
    alpha_index = []
    for char in sentence.upper():
        if char.isalpha() and 65 <= ord(char) <= 90:    # 65: A ascii value, 90: Z ascii value
            alpha_index.append(str(ord(char) - 64))
    
    return " ".join(alpha_index)

One drawback of this approach, as Luke Woodward pointed out in his comment to your question, is that if we have non-standard character, as accented letters, they get filtered out. If that is the case, you might want to expand either the regex or the ASCII filtering.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...