Input is a string, the idea is to count the letters A-z only, and print them alphabetically with the count of appearances.
As usual I kept at this 'till I got a working result, but now seek to optimize it in order to better understand the Python way of doing things.
def string_lower_as_list(string):
"""
>>> string_lower_as_list('a bC')
['a', ' ', 'b', 'c']
"""
return list(string.lower())
from sys import argv
letters = [letter for letter in string_lower_as_list(argv[1])
if ord(letter) < 124 and ord(letter) > 96]
uniques = sorted(set(letters))
for let in uniques:
print let, letters.count(let)
How do I remove the duplication of ord(letter) in the list comprehension?
Would there have been any benefit in using a Dictionary or Tuple in this instance, if so, how?
EDIT
Should have said, Python 2.7 on win32
You can compare letters directly and you actually only need to compare lower case letters
letters = [letter for letter in string_lower_as_list(argv[1])
if "a" <= letter <= "z"]
But better would be to use a dictionary to count the values. letters.count has to traverse the list every time you call it. But you are already traversing the list to filter out the right characters, so why not count them at the same time?
letters = {}
for letter in string_lower_as_list(argv[1]):
if "a" <= letter <= "z":
letters[letter] = letters.get(letter, 0) + 1
for letter in sorted(letters):
print letter, letters[letter]
Edit: As the others said, you don't have to convert the string to a list. You can iterate over it directly: for letter in argv[1].lower().
How do I remove the duplication of ord(letter) in the list comprehension?
You can use a very Python-specific and somewhat magical idiom that doesn't work in other languages: if 96 < ord(letter) < 124.
Would there have been any benefit in using a Dictionary or Tuple in this instance, if so, how?
You could try using the collections.Counter class added in Python 2.7.
P.S. You don't need to convert the string to a list in order to iterate over it in the list comprehension. Any iterable will work, and strings are iterable.
P.S. 2. To get the property 'this letter is alphabetic', instead of lowercasing and comparing to a range, just use str.isalpha. Unicode objects provide the same method, which allows the same code to Just Work with text in foreign languages, without having to know which characters are "letters". :)
You don't have to convert string to list, string is iterable:
letters = {}
for letter in argv[1].lower():
if "a" <= letter <= "z":
letters[letter] = letters.get(letter, 0) + 1
for letter in sorted(letters.keys()):
print letter, letters[letter]
Related
I am trying to remove certain characters from a string and it was suggested that i try and make a new string and just add characters that meet my criteria. I use a for loop to iterate through the string but then characters arent added to the new string-it prints a blank string. Ill include an ss.
you should use the in operator for comparing a value with multiple other values:
if s[i] not in 'AEIOUaeiou' or s[i-1] == ' ':
# if you prefer lists / tuples / sets of characters, you can use those instead:
# if s[i] not in ['A', 'E', 'I', 'O', ...]
answer_string += s[i]
You should use:
answer_string += s[i]
As, your current statement answer_string + s is not doing what you are hoping for.
This is what I understood from the given context. It would be better if you could post a code snippet with reference for better understanding the issue.
You have to check the character with each on it's own. That would be:
if s[i] != "A" or s[i] != "B" ... :
A more elegant solution would be:
if s[i] not in ["ABCD..."]:
Also what #avats said, you should be adding the single character, not the whole string
answer_string += s[i]
To make the checking case insensitive, so you wouldn't have to type out all the uppercase letters and lowercase, use lower():
if s[i].lower() not in ["abcd"]:
I'm new to Python and I'm stuck in an exercise which tells me to provide a script printing every possible pairs of two letters, only lower case, one by line, ordered alphabetically and that is the closest thing that I could do
import string
x=string.ascii_lowercase
y=list(x)
for i in y:
print(i,end='')
for g in y:
print(g)
You only print the first letter of each pair once.
from string import ascii_lowercase as lowercase_letters
for first_letter in lowercase_letters:
for second_letter in lowercase_letters:
print(first_letter + second_letter)
Additionally:
You don't need to convert the string to a list, you can loop over a string just fine. In fact, that's how list(some_string) works!
I used more readable variable names.
Using from ... import means you don't need to have the additional assignment.
You need to print the i letter in the second for loop
import string
x=string.ascii_lowercase
for i in x:
for g in x:
print(i,g)
So the program will go through every letter in the first loop and will print then the whole alphabet, one by one, as the second letter in the second loop
word_list = ['WELCOME']
double_letters = []
for word in word_list:
for i,j in enumerate(word):
x = word[i:i+2]
if len(x) == 2:
double_letters.append(x)
print(double_letters)
If you are given a list of words. Then this is one possible way
Try this code this will print in alphabetic order
You have studied ASCII code so what it does is it loops through 97 to 122 which contains all the alphabets and then it joins them.
for firstchar in range(97, 123):
for secondchar in range(97, 123):
print(chr(firstchar) + chr(secondchar))
If use string module it is very simple task:
import string
for firstchar in string.ascii_lowercase:
for secondchar in string.ascii_lowercase:
print(firstchar + secondchar)
So, I had a similar exercise on my IT classes: 'Print a string without characters appearing more than once (if they appear more than once, remove them)'. I thought that it was easy (and maybe it is), but I have completely no idea how to do that. I can do similar exercises (print all unique characters from a string / remove duplicates etc).
Example:
Input: '12345555555678'
Output: '1234678'
basic algorithm for this is described in this answer- for each char you check if it appears more than once by counting it's occurrences in the string.
However that's fairly inefficient, since it goes trough the string n ^ 2. You can improve that with the expense of some memory (which is illustrated in this answer - but obfuscated by a library).
The algorithm would then be to go once trough the string and count the number of occurrences for each char and save them somewhere, then go again trough the string and print only the chars that have the count 1.
inp = '1345552225555678'
counts = {};
for ch in inp:
if ch in counts:
counts[ch] = counts[ch] + 1
else:
counts[ch] = 1
result = '';
for ch in inp:
if counts[ch] == 1:
result = result + ch
print result
Arguably, this would be O(n) since the access time for a dictionary is generally considered O(1) (see this question for a discussion)
Note: Usually this is done using an array the size of the number legal chars, but since strings in python are Unicode, an array would be huge, however the access time would be truly O(1);
You could use collections.Counter().
from collections import Counter
inp = '12345555555678'
c = Counter(inp)
output = ''.join(k for k, v in c.items() if v == 1) # -> 1234678
Simple implementation of Counter
c = {}
for char in inp:
c[char] = c.get(char, 0) + 1
This should look like what you want
input_str = 'ahuadvzudnioqdazvyduazdazdui'
for c in input_str:
if input_str.count(c)==1:
print(c)
It's easier to understand, but note that it has quite low performance (Complexity of O(n^2)).
To make it little faster you can use List Comprehension.
input_str = '12345555555678'
[x for x in input_str if input_str.count(x) == 1]
If order of the element doesn't matter to you the iterating over set of the list will be beneficial.
If you convert list into set using set(input_str) then it will have unique values which may evantually reduce search space.
Then you can apply list complrehension.
input_str = '12345555555678'
[x for x in set(input_str) if input_str.count(x) == 1]
Note: Do not forget the condition that order will not be preserved after converting to set.
i_str = '12345555555678'
b = sorted(i_str)
for i in range(len(b)-1):
if b[i] == b[i+1]:
i_str = i_str.replace(b[i],'')
You just sort the string and compare each nth element with next element.If it is not same it is unique.
Also I am pretty sure it should be faster than using count function which will iterate though all the string for each unique element and check if the count of character is not greater than 1.
I solved a similar task on the codeacademy. I was requested to define a function that removes all vowels, even if it repeats. My code that allows to remove repeating symbols is below:
def anti_vowel(text):
all_vowels = ["A", "E", "U", "I", "O", "a", "e", "o", "u", "i"]
listed_text = []
for letter in text:
listed_text.append(letter)
for vowel in all_vowels:
while vowel in listed_text:
listed_text.remove(vowel)
return "".join(listed_text)
print(anti_vowel("Hey look Words!"))
output:
Hy lk Wrds!
This is my code, but it doesn't work. It should read text from the console, split it into words and distribute them into 3 lists and use separators between them.
words = list(map(str, input().split(" ")))
lowercase_words = []
uppercase_words = []
mixedcase_words = []
def split_symbols(list):
from operator import methodcaller
list = words
map(methodcaller(str,"split"," ",",",":",";",".","!","( )","","'","\\","/","[ ]","space"))
return list
for word in words:
if words[word] == word.lower():
words[word] = lowercase_words
elif words[word] == word.upper():
words[word] = uppercase_words
else:
words[word] = mixedcase_words
print(f"Lower case: {split_symbols(lowercase_words)}")
print(f"Upper case: {split_symbols(uppercase_words)}")
print(f"Mixed case: {split_symbols(mixedcase_words)}")
There are several issues in your code.
1) words is a list and word is string. And you are trying to access the list with the index as string which will throw an error. You must use integer for indexing a list. In this case, you don't even need indexes.
2) To check lower or upper case you can just do, word == word.lower() or word == word.upper(). Or another approach would be to use islower() or isupper() function which return a boolean.
3) You are trying to assign an empty list to that element of list. What you want is to append the word to that particular list. You want something like lowercase_words.append(word). Same for uppercase and mixedcase
So, to fix this two issues you can write the code like this -
for word in words:
if word == word.lower(): # same as word.islower()
lowercase_words.append(word)
elif word == word.upper(): # same as word.isupper()
uppercase_words.append(word)
else:
mixedcase_words.append(word)
My advice would be to refrain from naming variable things like list. Also, in split_words() you are assigning list to words. I think you meant it other way around.
Now I am not sure about the "use separators between them" part of the question. But the line map(methodcaller(str,"split"," ",",",":",";",".","!","( )","","'","\\","/","[ ]","space")) is definitely wrong. map() takes a function and an iterable. In your code the iterable part is absent and I think this where the input param list fits in. So, it may be something like -
map(methodcaller("split"," "), list)
But then again I am not sure what are you trying to achieve with that many seperator
I'm absolutely terrible at Python and my Computer Programming class ends in two days (thank god), but I am having the hardest time figuring out what is probably the easiest code ever.
The instructions to my assignment state, "Write a program which reads in text until a '!' is found. Use an array of integers subscripted by the letters 'A' through 'Z'."
From what i have done so far:
msg = input("What is your message? ")
msg = msg.upper()
int_array = [0] * 26
for alph in range (65, 91):
char = chr(alph)
print(char)
(int_array[char])
any help would be greatly appreciated! thanks!
EDIT: This is the full assignment:
Write a program which reads in text from the keyboard until a ('!') is found.
Using an array of integers subscripted by the letters 'A' through 'Z', count the number occurrences of each letter (regardless of whether it is upper or lower case). In a separate counter, also count the total number of "other" characters ('.', '?', ' ', '2', etc.).
Print out the count for each letter found. Also, print the count of the non-letter characters.
By inspecting the array, print out the count of the number of vowels, and the number of consonants.
Print out which letter was found the most times. (Note there may be more than one letter which has the maximum count attached to it.) Print out which letter (or letters) was found the least number of times, but make certain to exclude letters which were not found at all.
UPDATE:
I have gotten this far with my code
msg = input("What is your message? ")
print ()
num_alpha = 26
int_array = [0] * num_alpha
for alpha in range(num_alpha):
int_array[alpha] = chr(alpha + 65)
print(int_array[alpha], end = "")
print()
lett = 0
otherch = 0
num_vowels = 0
num_consanants = 0
count_character = [0] * 100000
length = len(msg)
for character in msg.upper():
if character == "!":
print("lett =", lett)
print("other char = ", otherch)
print("num_vowels = ", num_vowels)
print("num_consanants = ", num_consanants)
elif character < "A" or letter > "Z":
otherch = otherch + 1
count_character[ord(character)] = count_character[ord(character)] + 1
else:
lett = lett + 1
count_character[ord(character)] = count_character[ord(character)] + 1
for character in msg:
print("character", character, "appeared" , count_character[ord(character)] , "times")
it's obviously not finished yet, but every time i print the last print statement, it says that each character appeared 0 times. can anybody help?
You're going to need to get clarification on this, because there's no such thing as "an array of integers subscripted by the letters 'A' through 'Z'" in Python.
Possible interpretations that I can think of:
It's supposed to be a dictionary rather than an array. Python dictionaries are similar to lists (the Python datatype that is roughly equivalent to "arrays" in other languages), but they can be subscripted by strings, whereas lists can be subscripted only by integers. This way, you can store an integer to be associated with each letter. This is how most Python programmers would generally do something like this.
You're supposed to use parallel lists. You can do this by making two lists of 26 elements each, one containing the letters 'A' through 'Z' and one containing integers. For each letter, you could then use the list.index method to find the index in the first list where that letter is, then look up that index in the second list. (In theory, you wouldn't really need the first list, since Python strings are like lists in that they can be subscripted with integers and support the index method. So you could use the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' instead of a list. Or you could use the ord function, which is the inverse of the chr function. But I don't know if you're supposed to use these features.)
I'm not 100% sure the following is right because I agree with the others that the assignment description is wonky. It looks like a C-based homework assignment lazily ported to Python. That said:
In principle rather than hardcoding the bounds of the alphabet I'd go with ord('A') and ord('Z')+1, so that I can say something like alphabet = list(range(ord('A'), ord('Z')+1))
Renaming int_array to counter might make it more obvious what you need to do in your inner loop (keeping in mind that you're using the letters as your indices. Or rather, you'd need something more like ord(letter)-ord('A') as your indices)
You don't want to loop over the alphabet; you want to loop over the input.
count should be initialized to [0]*27 to track "other" values. You can increment counter[-1] for non-alphabetic characters.
Your final value is chr of counter.index(max(counter)). You may find it more straightforward, or your teacher may find it more acceptable, to just write a for loop.