Given a list of lowercase strings named mystrings, create and return a dictionary whose keys are the unique first characters of the strings and whose values are lists of words beginning with those characters, in the same order that they appear in the list of strings. Ignore case: you can assume that all words are lowercase. A sample list of strings is given below, but your code should work on any list of strings of any length. You do not have to write a function.
mystrings = ["banana", "xylophone", "duck", "carriage", "bandana", "diamond", "cardinal"]
output is {'b': ['banana', 'bandana'], 'x': ['xylophone'], 'd': ['duck', 'diamond'],
'c': ['carriage', 'cardinal']}
I have tried using a loop but am getting stuck.
Use a loop and dict's setdefault:
mystrings = ["banana", "xylophone", "duck", "carriage", "bandana", "diamond", "cardinal"]
out = {}
for word in mystrings:
out.setdefault(word[0], []).append(word)
Output:
{'b': ['banana', 'bandana'],
'x': ['xylophone'],
'd': ['duck', 'diamond'],
'c': ['carriage', 'cardinal']}
One-liner loop:
mystrings_dict = {k: [w for w in mystrings_list if w[0] == k] for k in set([w[0] for w in mystrings_list])}
Traditional loop:
mystrings_list = ["banana", "xylophone", "duck", "carriage", "bandana", "diamond", "cardinal"]
mystrings_dict = dict()
for word in mystrings_list:
firstletter = word[0] # 0th element of string is first letter
if firstletter in mystrings_dict:
mystrings_dict[firstletter].append(word)
else:
mystrings_dict[firstletter] = [word]
Results:
print(mystrings_dict)
>> {'b': ['banana', 'bandana'], 'x': ['xylophone'], 'd': ['duck', 'diamond'], 'c': ['carriage', 'cardinal']}
You will look for every word in words, if the first letter of a word is not in the solution dictionary you will create a list associated to that letter, if not, that means that exist a list in that letter (in the dictionary) with at least a word inside, then you add the new word to that list.
words = ["banana", "xylophone", "duck", "carriage", "bandana", "diamond", "cardinal"]
sol={}
for w in words:
if w[0] not in sol:
sol[w[0]] = []
sol[w[0]].append(w)
print(sol)
I’m a programming neophyte and would like some assistance in understanding why the following algorithm is behaving in a particular manner.
My objective is for the function to read in a text file containing words (can be capitalized), strip the whitespace, split the items into separate lines, convert all capital first characters to lowercase, remove all single characters (e.g., “a”, “b”, “c”, etc.), and add the resulting words to a list. All words are to be a separate item in the list for further processing.
Input file:
A text file (‘sample.txt’) contains the following data - “a apple b Banana c cherry”
Desired output:
[‘apple’, ‘banana’, ‘cherry’]
In my initial attempt I tried to iterate through the list of words to test if their length was equal to 1. If so, the word was to be removed from the list, with the other words remaining in the list. This resulted in the following, non-desired output: [None, None, None]
filename = ‘sample.txt’
with open(filename) as input_file:
word_list = input_file.read().strip().split(' ')
word_list = [word.lower() for word in word_list]
word_list = [word_list.remove(word) for word in word_list if len(word) == 1]
print(word_list)
Produced non-desired output = [None, None, None]
My next attempt was to instead iterate through the list for words to test if their length was greater than 1. If so, the word was to be added to the list (leaving the single characters behind). The desired output was achieved using this method.
filename = ‘sample.txt’
with open(filename) as input_file:
word_list = input_file.read().strip().split(' ')
word_list = [word.lower() for word in word_list]
word_list = [word for word in word_list if len(word) > 1]
print(word_list)
Produced desired Output = [‘apple’, ‘banana’, ‘cherry’]
My questions are:
Why didn’t the initial code produce the desired result when it seemed to be the most logical and most efficient?
What is the best ‘Pythonic’ way to achieve the desired result?
The reason you got the output you got is
You're removing items from the list as you're looping through it
You are trying to use the output of list.remove (which just modifies the list and returns None)
Your last list comprehension (word_list = [word_list.remove(word) for word in word_list if len(word) == 1]) is essentially equivalent to this:
new_word_list = []
for word in word_list:
if len(word) == 1:
new_word_list.append(word_list.remove(word))
word_list = new_word_list
And as you loop through it this happens:
# word_list == ['a', 'apple', 'b', 'banana', 'c', 'cherry']
# new_word_list == []
word = word_list[0] # word == 'a'
new_word_list.append(word_list.remove(word))
# word_list == ['apple', 'b', 'banana', 'c', 'cherry']
# new_word_list == [None]
word = word_list[1] # word == 'b'
new_word_list.append(word_list.remove(word))
# word_list == ['apple', 'banana', 'c', 'cherry']
# new_word_list == [None, None]
word = word_list[2] # word == 'c'
new_word_list.append(word_list.remove(word))
# word_list == ['apple', 'banana', 'cherry']
# new_word_list == [None, None, None]
word_list = new_word_list
# word_list == [None, None, None]
The best 'Pythonic' way to do this (in my opinion) would be:
with open('sample.txt') as input_file:
file_content = input_file.read()
word_list = []
for word in file_content.strip().split(' '):
if len(word) == 1:
continue
word_list.append(word.lower())
print(word_list)
In your first approach, you are storing the result of word_list.remove(word) in the list which is None. Bcz list.remove() method return nothing but performing action on a given list.
Your second approach is the pythonic way to achieve your goal.
The second attempt is the most pythonic. The first one can still be achieved with the following:
filename = 'sample.txt'
with open(filename) as input_file:
word_list = input_file.read().strip().split(' ')
word_list = [word.lower() for word in word_list]
for word in word_list:
if len(word) == 1:
word_list.remove(word)
print(word_list)
Why didn’t the initial code produce the desired result when it seemed
to be the most logical and most efficient?
It's advised to never alter a list while iterating over it. This is because it is iterating over a view of the initial list and that view will differ from the original.
What is the best ‘Pythonic’ way to achieve the desired result?
Your second attempt. But I'd use a better naming convention and your comprehensions can be combined as you're only making them lowercase in the first one:
word_list = input_file.read().strip().split(' ')
filtered_word_list = [word.lower() for word in word_list if len(word) > 1]
so basically it would be like:
MyList=["Monkey","Phone","Metro","Boom","Feet"]
and let's say I have the input be m so Boom and Monkey and Metro would be put in a list like so
output >> ["Monkey","Metro","Feet"]
and if I would've had the input be f then the output would be
output >> ["Feet"]
and my question is how would I put this in a def? This is what I came up with
def Find(word,MyList):
MyList2=[]
count=0
for i in MyList:
count+=1
if i[count] == MyList2: ##(at first i did if i[0:10])
for x in range(1):
MyList2.append(i)
print(MyList2)
and then somewhere there should be
word=input("Word, please.")
and then
Find(word,MyList)
thanks in advance!
Try this :
def find_words(input_char, my_list):
ret_list = []
for i in my_list:
if input_char.lower() in i.lower():
ret_list.append(i)
return ret_list
MyList=["Monkey","Phone","Metro","Boom","Feet"]
input_char=input("Input a character :").strip() # get a character and strip spaces if any.
find_words(input_char, MyList) # call the function with arguments
Output for sample input "M :
Input a character :>? "M"
>>> ['Monkey', 'Metro', 'Boom']
(Almost) One liner:
>>> MyList=["Monkey","Phone","Metro","Boom","Feet"]
>>> target = input("Input string: ")
Input string: Ph
>>> print([i for i in MyList if target.lower() in i.lower()])
['Phone']
Generally in Python you don't want to be playing with indexes, iterators are the way to go.
The in keyword checks for substrings so it will work whether you provide only one character or a full string too (i.e. if you input Ph you'll get a list containing only Phone)
Depending on how efficient you want your search would be. Throwing in one more approach to build a dictionary like this
from collections import defaultdict
d = defaultdict(set)
for i in MyList:
chars = set(i)
for c in chars:
d[c].add(i)
Now, your dictionary looks like this
defaultdict(set,
{'o': {'Boom', 'Metro', 'Monkey', 'Phone'},
'k': {'Monkey'},
'e': {'Feet', 'Metro', 'Monkey', 'Phone'},
'M': {'Metro', 'Monkey'},
'y': {'Monkey'},
'n': {'Monkey', 'Phone'},
'h': {'Phone'},
'P': {'Phone'},
't': {'Feet', 'Metro'},
'r': {'Metro'},
'm': {'Boom'},
'B': {'Boom'},
'F': {'Feet'}})
Now, you can simply search within your dict with O(1) complexity
d[your_input_char]
Here is how you can use a list comprehension:
def Find(letter, MyList):
print([word for word in MyList if letter.lower() in word.lower()])
Find('m', ["Monkey","Phone","Metro","Boom","Feet"])
Output:
['Monkey', 'Metro', 'Boom']
This question already has answers here:
How do I split a string into a list of words?
(9 answers)
Using a dictionary to count the items in a list
(8 answers)
Closed yesterday.
I want to take every word from a text file, and count the word frequency in a dictionary.
Example: 'this is the textfile, and it is used to take words and count'
d = {'this': 1, 'is': 2, 'the': 1, ...}
I am not that far, but I just can't see how to complete it. My code so far:
import sys
argv = sys.argv[1]
data = open(argv)
words = data.read()
data.close()
wordfreq = {}
for i in words:
#there should be a counter and somehow it must fill the dict.
If you don't want to use collections.Counter, you can write your own function:
import sys
filename = sys.argv[1]
fp = open(filename)
data = fp.read()
words = data.split()
fp.close()
unwanted_chars = ".,-_ (and so on)"
wordfreq = {}
for raw_word in words:
word = raw_word.strip(unwanted_chars)
if word not in wordfreq:
wordfreq[word] = 0
wordfreq[word] += 1
for finer things, look at regular expressions.
Although using Counter from the collections library as suggested by #Michael is a better approach, I am adding this answer just to improve your code. (I believe this will be a good answer for a new Python learner.)
From the comment in your code it seems like you want to improve your code. And I think you are able to read the file content in words (while usually I avoid using read() function and use for line in file_descriptor: kind of code).
As words is a string, in for loop, for i in words: the loop-variable i is not a word but a char. You are iterating over chars in the string instead of iterating over words in the string words. To understand this, notice following code snippet:
>>> for i in "Hi, h r u?":
... print i
...
H
i
,
h
r
u
?
>>>
Because iterating over the given string char by chars instead of word by words is not what you wanted to achieve, to iterate words by words you should use the split method/function from string class in Python.
str.split(str="", num=string.count(str)) method returns a list of all the words in the string, using str as the separator (splits on all whitespace if left unspecified), optionally limiting the number of splits to num.
Notice the code examples below:
Split:
>>> "Hi, how are you?".split()
['Hi,', 'how', 'are', 'you?']
loop with split:
>>> for i in "Hi, how are you?".split():
... print i
...
Hi,
how
are
you?
And it looks like something you need. Except for word Hi, because split(), by default, splits by whitespaces so Hi, is kept as a single string (and obviously) you don't want that.
To count the frequency of words in the file, one good solution is to use regex. But first, to keep the answer simple I will be using replace() method. The method str.replace(old, new[, max]) returns a copy of the string in which the occurrences of old have been replaced with new, optionally restricting the number of replacements to max.
Now check code example below to see what I suggested:
>>> "Hi, how are you?".split()
['Hi,', 'how', 'are', 'you?'] # it has , with Hi
>>> "Hi, how are you?".replace(',', ' ').split()
['Hi', 'how', 'are', 'you?'] # , replaced by space then split
loop:
>>> for word in "Hi, how are you?".replace(',', ' ').split():
... print word
...
Hi
how
are
you?
Now, how to count frequency:
One way is use Counter as #Michael suggested, but to use your approach in which you want to start from empty an dict. Do something like this code sample below:
words = f.read()
wordfreq = {}
for word in .replace(', ',' ').split():
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
# ^^ add 1 to 0 or old value from dict
What am I doing? Because initially wordfreq is empty you can't assign it to wordfreq[word] for the first time (it will raise key exception error). So I used setdefault dict method.
dict.setdefault(key, default=None) is similar to get(), but will set dict[key]=default if key is not already in dict. So for the first time when a new word comes, I set it with 0 in dict using setdefault then add 1 and assign to the same dict.
I have written an equivalent code using with open instead of single open.
with open('~/Desktop/file') as f:
words = f.read()
wordfreq = {}
for word in words.replace(',', ' ').split():
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
print wordfreq
That runs like this:
$ cat file # file is
this is the textfile, and it is used to take words and count
$ python work.py # indented manually
{'and': 2, 'count': 1, 'used': 1, 'this': 1, 'is': 2,
'it': 1, 'to': 1, 'take': 1, 'words': 1,
'the': 1, 'textfile': 1}
Using re.split(pattern, string, maxsplit=0, flags=0)
Just change the for loop: for i in re.split(r"[,\s]+", words):, that should produce the correct output.
Edit: better to find all alphanumeric character because you may have more than one punctuation symbols.
>>> re.findall(r'[\w]+', words) # manually indent output
['this', 'is', 'the', 'textfile', 'and',
'it', 'is', 'used', 'to', 'take', 'words', 'and', 'count']
use for loop as: for word in re.findall(r'[\w]+', words):
How would I write code without using read():
File is:
$ cat file
This is the text file, and it is used to take words and count. And multiple
Lines can be present in this file.
It is also possible that Same words repeated in with capital letters.
Code is:
$ cat work.py
import re
wordfreq = {}
with open('file') as f:
for line in f:
for word in re.findall(r'[\w]+', line.lower()):
wordfreq[word] = wordfreq.setdefault(word, 0) + 1
print wordfreq
Used lower() to convert an upper letter to lower letter.
output:
$python work.py # manually strip output
{'and': 3, 'letters': 1, 'text': 1, 'is': 3,
'it': 2, 'file': 2, 'in': 2, 'also': 1, 'same': 1,
'to': 1, 'take': 1, 'capital': 1, 'be': 1, 'used': 1,
'multiple': 1, 'that': 1, 'possible': 1, 'repeated': 1,
'words': 2, 'with': 1, 'present': 1, 'count': 1, 'this': 2,
'lines': 1, 'can': 1, 'the': 1}
from collections import Counter
t = 'this is the textfile, and it is used to take words and count'
dict(Counter(t.split()))
>>> {'and': 2, 'is': 2, 'count': 1, 'used': 1, 'this': 1, 'it': 1, 'to': 1, 'take': 1, 'words': 1, 'the': 1, 'textfile,': 1}
Or better with removing punctuation before counting:
dict(Counter(t.replace(',', '').replace('.', '').split()))
>>> {'and': 2, 'is': 2, 'count': 1, 'used': 1, 'this': 1, 'it': 1, 'to': 1, 'take': 1, 'words': 1, 'the': 1, 'textfile': 1}
The following takes the string, splits it into a list with split(), for loops the list and counts
the frequency of each item in the sentence with Python's count function count (). The
words,i, and its frequency are placed as tuples in an empty list, ls, and then converted into
key and value pairs with dict().
sentence = 'this is the textfile, and it is used to take words and count'.split()
ls = []
for i in sentence:
word_count = sentence.count(i) # Pythons count function, count()
ls.append((i,word_count))
dict_ = dict(ls)
print dict_
output; {'and': 2, 'count': 1, 'used': 1, 'this': 1, 'is': 2, 'it': 1, 'to': 1, 'take': 1, 'words': 1, 'the': 1, 'textfile,': 1}
sentence = "this is the textfile, and it is used to take words and count"
# split the sentence into words.
# iterate thorugh every word
counter_dict = {}
for word in sentence.lower().split():
# add the word into the counter_dict initalize with 0
if word not in counter_dict:
counter_dict[word] = 0
# increase its count by 1
counter_dict[word] =+ 1
#open your text book,Counting word frequency
File_obj=open("Counter.txt",'r')
w_list=File_obj.read()
print(w_list.split())
di=dict()
for word in w_list.split():
if word in di:
di[word]=di[word] + 1
else:
di[word]=1
max_count=max(di.values())
largest=-1
maxusedword=''
for k,v in di.items():
print(k,v)
if v>largest:
largest=v
maxusedword=k
print(maxusedword,largest)
you can also use default dictionaries with int type.
from collections import defaultdict
wordDict = defaultdict(int)
text = 'this is the textfile, and it is used to take words and count'.split(" ")
for word in text:
wordDict[word]+=1
explanation:
we initialize a default dictionary whose values are of the type int. This way the default value for any key will be 0 and we don't need to check if a key is present in the dictionary or not. we then split the text with the spaces into a list of words. then we iterate through the list and increment the count of the word's count.
wordList = 'this is the textfile, and it is used to take words and count'.split()
wordFreq = {}
# Logic: word not in the dict, give it a value of 1. if key already present, +1.
for word in wordList:
if word not in wordFreq:
wordFreq[word] = 1
else:
wordFreq[word] += 1
print(wordFreq)
My approach is to do few things from ground:
Remove punctuations from the text input.
Make list of words.
Remove empty strings.
Iterate through list.
Make each new word a key into Dictionary with value 1.
If a word is already exist as key then increment it's value by one.
text = '''this is the textfile, and it is used to take words and count'''
word = '' #This will hold each word
wordList = [] #This will be collection of words
for ch in text: #traversing through the text character by character
#if character is between a-z or A-Z or 0-9 then it's valid character and add to word string..
if (ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z') or (ch >= '0' and ch <= '9'):
word += ch
elif ch == ' ': #if character is equal to single space means it's a separator
wordList.append(word) # append the word in list
word = '' #empty the word to collect the next word
wordList.append(word) #the last word to append in list as loop ended before adding it to list
print(wordList)
wordCountDict = {} #empty dictionary which will hold the word count
for word in wordList: #traverse through the word list
if wordCountDict.get(word.lower(), 0) == 0: #if word doesn't exist then make an entry into dic with value 1
wordCountDict[word.lower()] = 1
else: #if word exist then increament the value by one
wordCountDict[word.lower()] = wordCountDict[word.lower()] + 1
print(wordCountDict)
Another approach:
text = '''this is the textfile, and it is used to take words and count'''
for ch in '.\'!")(,;:?-\n':
text = text.replace(ch, ' ')
wordsArray = text.split(' ')
wordDict = {}
for word in wordsArray:
if len(word) == 0:
continue
else:
wordDict[word.lower()] = wordDict.get(word.lower(), 0) + 1
print(wordDict)
One more function:
def wcount(filename):
counts = dict()
with open(filename) as file:
a = file.read().split()
# words = [b.rstrip() for b in a]
for word in a:
if word in counts:
counts[word] += 1
else:
counts[word] = 1
return counts
def play_with_words(input):
input_split = input.split(",")
input_split.sort()
count = {}
for i in input_split:
if i in count:
count[i] += 1
else:
count[i] = 1
return count
input ="i,am,here,where,u,are"
print(play_with_words(input))
Write a Python program to create a list of strings by taking input from the user and then create a dictionary containing each string along with their frequencies. (e.g. if the list is [‘apple’, ‘banana’, ‘fig’, ‘apple’, ‘fig’, ‘banana’, ‘grapes’, ‘fig’, ‘grapes’, ‘apple’] then output should be {'apple': 3, 'banana': 2, 'fig': 3, 'grapes': 2}.
lst = []
d = dict()
print("ENTER ZERO NUMBER FOR EXIT !!!!!!!!!!!!")
while True:
user = input('enter string element :: -- ')
if user == "0":
break
else:
lst.append(user)
print("LIST ELEMENR ARE :: ",lst)
l = len(lst)
for i in range(l) :
c = 0
for j in range(l) :
if lst[i] == lst[j ]:
c += 1
d[lst[i]] = c
print("dictionary is :: ",d)
You can also go with this approach. But you need to store the text file's content in a variable as a string first after reading the file.
In this way, You don't need to use or import any external libraries.
s = "this is the textfile, and it is used to take words and count"
s = s.split(" ")
d = dict()
for i in s:
c = ""
if i.isalpha() == True:
if i not in d:
d[i] = 1
else:
d[i] += 1
else:
for j in i:
l = len(j)
if j.isalpha() == True:
c+=j
if c not in d:
d[c] = 1
else:
d[c] += 1
print(d)
Result: