Python: Counting characters and displaying them in alphabetical order?

Question:

So I have to program something in Python that takes a string that’s 20 characters or more, count how often each character comes up, and display the count in Alphabetical order with caps and lowercase letters mixed (A-a-B-b-C-c).

The phrase I’m testing is "She sells sea shells down by the seashore" which should display as:
{‘ ‘: 7, ‘a’: 2, ‘b’: 1, ‘d’: 1, ‘e’: 7, ‘h’: 4, ‘l’: 4, ‘n’: 1, ‘o’: 2, ‘r’: 1, ‘S’: 1, ‘s’: 7, ‘t’: 1, ‘w’: 1, ‘y’: 1}

However, I can’t figure out how to get it to count and sort out the way I want it. Here is what I tried.

#This first one sorted and counted it alphabetically, however the uppercase and lowercase letters didn't stay together.

def main():
    input_str = str(input("Please enter a phrase:n"))
    if len(input_str) < 20:
        print("Please enter a phrase that's 20 characters or more.")
    else:
        res = {}
        for keys in sorted(input_str):
            res[keys]=res.get(keys,0)+1
        print("Count of all characters in inputed phrase is:n"+ str(res))

        
main()
Please enter a phrase:
She sells sea shells down by the seashore
Count of all characters in inputed phrase is:
{' ': 7, 'S': 1, 'a': 2, 'b': 1, 'd': 1, 'e': 7, 'h': 4, 'l': 4, 'n': 1, 'o': 2, 'r': 1, 's': 7, 't': 1, 'w': 1, 'y': 1}
#This second one I saw the lambda command and thought it would fix it, however it doesn't actually count the letters, it just displays them in alphabetical order

def main():
    input_str = str(input("Please enter a phrase:n"))
    if len(input_str) < 20:
        print("Please enter a phrase that's 20 characters or more.")
    else:
        sorted_list = sorted(input_str , key = lambda s: (s.upper(),s))
        print("Count of all characters in inputed phrase is:n", sorted_list)

        
main()
Please enter a phrase:
She sells sea shells down by the seashore
Count of all characters in inputed phrase is:
 [' ', ' ', ' ', ' ', ' ', ' ', ' ', 'a', 'a', 'b', 'd', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'h', 'h', 'h', 'h', 'l', 'l', 'l', 'l', 'n', 'o', 'o', 'r', 'S', 's', 's', 's', 's', 's', 's', 's', 't', 'w', 'y']

How do I combine these so that it will count and sort them the way I want? Or am I going about this the wrong way?

Asked By: ForeverLost20

||

Answers:

The lambda itself couldn’t fix it, because it’s not giving you the counts. It only helps to sort the characters in the input string.
Once you have that list of sorted characters you can use e.g. a dict comprehension to assign counts to each character and then print it:

def main():
    input_str = input("Please enter a phrase:n")
    if len(input_str) < 20:
        print("Please enter a phrase that's 20 characters or more.")
    else:
        sorted_list = sorted(input_str , key = lambda s: (s.upper(),s))
        character_counts = {item: input_str.count(item) for item in sorted_list}
        print(f"Count of all characters in inputed phrase is:n{character_counts}")

# Input:
# oasjdoasdjoasdjasodjasopdnaosdn
# Output:
#  {'a': 6, 'd': 6, 'j': 4, 'n': 2, 'o': 6, 'p': 1, 's': 6}

Side notes:

  • f-string is a newer way of formatting strings
  • input returns a string by default, no need to explicitly cast it
  • passing a lambda to sorting functions is just a convention and is often convenient, but it’s not a "must do". You can pass any named function as well, since that key parameter is actually "how do you want me to sort the iterable"
    e.g.
# Define function
def get_upper_and_non_modified_char(c: str)->Tuple[str, str]:
    return s.upper(), s
...
...
...
# Use it for sorting instead of lambda
sorted_list = sorted(input_str , key = get_upper_and_non_modified_char)
Answered By: Gameplay

Your fundamental problem is that you want the results in a non-standard order

For computers, generally alphabetical order is usually ABCabc, and if you don’t care about capitalization, it becomes ABC (or abc). However you are doing something more subtle: retaining the case, and putting the capital of each letter before its lower case equivalent: AaBbCc.

I assume that you want the capital letter to always be before its corresponding lower case?

If so, you can construct a sort key composed of (say) the upper-case version of the character, after which you append an extra piece of string, that causes upper case to sort before lower case. For example, you can add a "1" for upper case and a "2" for lower case. The end-user never sees this: it is purely an intermediate step to yield your desired order.

A snippet like this would be the concept. For each key k, you would create a string like this which sets its sort order:

k.upper()+("1" if "A"<=k<="Z" else "2")

Your first program is already close

You just need it to list the keys in your desired order.

Instead of:

    print("Count of all characters in inputed phrase is:n"+ str(res))

try something like this:

    print("Count of all characters in inputed phrase is:")
    
    sorted_keys = sorted(res.keys(), key=lambda k:k.upper()+("1" if "A"<=k<="Z" else "2"))
    sorted_res = { k:res[k] for k in sorted_keys }
Answered By: Eureka
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.