im new on python 3.
What I want to do is to alternate upper and lowercase but only on a dictionary key.
my dictionary is created from a list, its key is the word (or list element) and its value is the times this element appears in the list.
kb = str(input("Give me a string: "));
txt = kb.lower(); #Turn string into lowercase
cadena = txt.split(); #Turn string into list
dicc = {};
for word in cadena:
if (word in dicc):
dicc[word] = dicc[word] + 1
else:
dicc[word] = 1
print(dicc)
With this code i can get for example:
input: "Hi I like PYthon i am UsING python"
{'hi': 1, 'i': 2, 'like': 1, 'python': 2, 'am': 1, 'using': 1}
but what I am trying to get is actually is:
{'hi': 1, 'I': 2, 'like': 1, 'PYTHON': 2, 'am': 1, 'USING': 1}
I tried using this:
for n in dicc.keys():
if (g%2 == 0):
n.upper()
else:
n.lower()
print(dicc)
But it seems that I have no idea of what I'm doing.
Any help would be appreciated.
Using itertools and collections.OrderedDict (to guarantee order in Python < 3.7)
Setup
import itertools
from collections import OrderedDict
s = 'Hi I like PYthon i am UsING python'
switcher = itertools.cycle((str.lower, str.upper))
d = OrderedDict()
final = OrderedDict()
First, create an OrderedDictionary just to count the occurences of strings in your list (since you want matches to be case insensitive based on your output):
for word in s.lower().split():
d.setdefault(word, 0)
d[word] += 1
Next, use itertools.cycle to call str.lower or str.upper on keys and create your final dictionary:
for k, v in d.items():
final[next(switcher)(k)] = v
print(final)
OrderedDict([('hi', 1), ('I', 2), ('like', 1), ('PYTHON', 2), ('am', 1), ('USING', 1)])
Your n in dicc.keys() line is wrong. You are trying to use n as both the position in the array of keys and the key itself.
Also the semicolons are unnecessary.
This should do what you want:
from collections import OrderedDict
# Receive user input
kb = str(input("Give me a string: "))
txt = kb.lower()
cadena = txt.split()
dicc = OrderedDict()
# Construct the word counter
for word in cadena:
if word in dicc:
dicc[word] += 1
else:
dicc[word] = 1
If you just want to print the output with alternating case, you can do something like this:
# Print the word counter with alternating case
elems = []
for i, (word, wordcount) in enumerate(dicc.items()):
if i % 2 == 0:
word = word.upper()
elems.append('{}: {}'.format(word, wordcount)
print('{' + ', '.join(elems) + '}')
Or you can make a new OrderedDict with alternating case...
dicc_alt_case = OrderedDict((word.upper() if (i % 2 == 0) else word, wordcount)
for word, wordcount in dicc.items())
Related
I was trying to find the occurrence of every 2 consecutive characters from a string.
The result will be in a dictionary as key = 2 characters and value = number of occurrence.
I tried the following :
seq = "AXXTAGXXXTA"
d = {seq[i:i+2]:seq.count(seq[i:i+2]) for i in range(0, len(seq)-1)}
The problem is that the result of XX should be 3 not 2 .
You can use collections.Counter.
from collections import Counter
seq = "AXXTAGXXXTA"
Counter((seq[i:i+2] for i in range(len(seq)-1)))
Output:
Counter({'AX': 1, 'XX': 3, 'XT': 2, 'TA': 2, 'AG': 1, 'GX': 1})
Or without additional libraries. You can use dict.setdefault.
seq = "AXXTAGXXXTA"
d = {}
for i in range(len(seq)-1):
key = seq[i:i+2]
d[key] = d.setdefault(key, 0) + 1
print(d)
This is what I have so far as a function
example = "Sample String"
def func(text, let):
count= {}
for let in text.lower():
let = count.keys()
if let in text:
count[let] += 1
else:
count[let] = 1
return count
I want to return something like this
print(func(example, "sao"))
{'s': 2, 'a' : 1}
I am not very sure what I could improve on
I would use Counter from the collections built-in module:
from collections import Counter
def func(text, let):
c = Counter(text.lower())
return {l: c[l] for l in let if l in c.keys()}
Breaking it down:
Counter will return the count of letters in your string:
In [5]: Counter(example.lower())
Out[5]:
Counter({'s': 2,
'a': 1,
'm': 1,
'p': 1,
'l': 1,
'e': 1,
' ': 1,
't': 1,
'r': 1,
'i': 1,
'n': 1,
'g': 1})
So then all you need to do is return a dictionary of the appropriate letters, which can be done in a dictionary comprehension:
# iterate over every letter in `let`, and get the Counter value for that letter,
# if that letter is in the Counter keys
{l: c[l] for l in let if l in c.keys()}
Fixing your code
If you prefer to use your approach, you could make your code work properly with this:
def func(text, let):
count = {}
for l in text.lower():
if l in let:
if l in count.keys():
count[l] += 1
else:
count[l] = 1
return count
from functools import reduce
def count(text, letters):
return reduce(
lambda d, letr: d.update({letr: d.get(letr, 0) + 1}) or d,
filter(lambda l: l in letters, text), {}
)
Read it backwards.
Creates an empty dictionary.
{}
Filters letters from text.
lambda l: l in letters
This lambda function returns true if l is in letters
filter(lambda l: l in letters, text)
reduce will iterate over the object returned by filter, which will
only produce letters in text, if they are in letters.
lambda d, letr: d.update({letr: d.get(letr, 0) + 1}) or d
Updates the dictionary with the count of the letters it encounters.
Each time reduce iterates over an item generated by the filter object,
it will call this lambda function. Since dict.update() -> None, returns None, which evaluates to false, we say or d to actually return the dict back to reduce, which will pass the dict back into the lambda the next time it gets called, thus building up the counts. We also use dict.get() in the lambda instead of d[i], this allows us to pass the default of 0 if the letter is not yet in the dictionary.
At the end reduce returns the dict, and we return that from count.
This is similar to how "map reduce" works.
You can read about functional style and lambda expressions in the python docs.
>>> def func(text: str, let: str):
... text, count = text.lower(), {}
... for i in let:
... if text.count(i) != 0:
... count[i] = text.count(i)
... return count
...
>>> print(func("Sample String", "sao"))
{'s': 2, 'a': 1}
I've got two problems with the following code
S = "acbcbba"
def count_letters(text):
result = {}
for letter in text:
if letter.isalpha():
if letter.lower() in result.keys():
result[letter.lower()] += 1
else:
result[letter.lower()] = 1
print(result)
return(result)
count_letters(S)
Firstly, I can't figure out how to modify it so it only returns 1 dictionary instead of as many dictionaries as there letters in the string.
Secondly, I then need to be able to access each key to figure out if the value associated with it is odd and return the keys that have odd values associated with them?
Does anyone have any ideas of how to do this?
It isn't returning multiple dictionaries, it is returning 1 dictionary, and printing the others. Just remove your print statement.
Regarding querying for items which have an odd number of counts you can use a list comprehension of the dictionary's items() and filter out by their value (i.e. count) being odd.
>>> d = count_letters(S)
>>> d
{'a': 2, 'c': 2, 'b': 3}
>>> [key for key, value in d.items() if value % 2 == 1]
['b']
If you want a list of the key value pairs then you can do something similar
>>> [(key, value) for key, value in d.items() if value % 2 ==1 ]
[('b', 3)]
All was about an indentation but here is a solution
S = "acbcbba"
def count_letters(text):
result = {}
for letter in text:
if letter.isalpha():
if letter.lower() in result.keys():
result[letter.lower()] += 1
else:
result[letter.lower()] = 1
print(result)
return(result)
count_letters(S)
output
{'a': 2, 'c': 2, 'b': 3}
anyway there was no reason to return if there is print in the function or you could return result only and thereafter print it like the following
S = "acbcbba"
def count_letters(text):
result = {}
for letter in text:
if letter.isalpha():
if letter.lower() in result.keys():
result[letter.lower()] += 1
else:
result[letter.lower()] = 1
return(result)
print(count_letters(S))
You can use built-in functions for that. For counting a specific character, just do S.count('a'). For getting a dictionary with all characters you could do something like that
S = "acbcbba"
my_dict = {k:S.count(k) for k in set(S)}
I'm having trouble transforming every word of a string in a dictionary and passing how many times the word appears as the value.
For example
string = 'How many times times appeared in this many times'
The dict i wanted is:
dict = {'times':3, 'many':2, 'how':1 ...}
Using Counter
from collections import Counter
res = dict(Counter(string.split()))
#{'How': 1, 'many': 2, 'times': 3, 'appeared': 1, 'in': 1, 'this': 1}
You can loop through the words and increment the count like so:
d = {}
for word in string.split(" "):
d.setdefault(word, 0)
d[word] += 1
I have the following sample data
docs_word = ["this is a test", "this is another test"]
docs_txt = ["this is a great test", "this is another test"]
What I want to do now is to create two dictionaries of the words in the sample files, compare them and store the words that are in the docs_txt file but not in the docs_word file in a seperate dictionary. Therefore I wrote the following:
count_txtDoc = Counter()
for file in docs_word:
words = file.split(" ")
count_txtDoc.update(words)
count_wrdDoc = Counter()
for file in docs_txt:
words = file.split(" ")
count_wrdDoc.update(words)
#Create a list of the dictionary keys
words_worddoc = count_wrdDoc.keys()
words_txtdoc = count_txtDoc.keys()
#Look for values that are in word_doc but not in txt_doc
count_all = Counter()
for val in words_worddoc:
if val not in words_txtdoc:
count_all.update(val)
print(val)
The thing now is that the correct values are printed. It shows: "great".
However if I print:
print(count_all)
I get the following output:
Counter({'a': 1, 'r': 1, 'e': 1, 't': 1, 'g': 1})
While I expected
Counter({'great': 1})
Any thoughts on how I can achieve this?
#
print(count_all)
Update the counter using an iterable containing the word, not the word itself (since the word is also iterable):
count_all.update([val])
# ^ ^
However, you may not need to create a new counter if you only the item. You can take the symmetric difference of the keys:
words_worddoc = count_wrdDoc.viewkeys() # use .keys() in Py3
words_txtdoc = count_txtDoc.viewkeys() # use .keys() in Py3
print(words_txtdoc ^ words_worddoc)
# set(['great'])
If you want the count also, you can compute the symmetric difference between both counters like so:
count_all = (count_wrdDoc - count_txtDoc) | (count_txtDoc - count_wrdDoc)
print (count_all)
# Counter({'great': 1})