I just want to print the key, not their index - python

I need to print the keys + their values and it always prints the index of the key too, how can I fix that?
def task_3_4(something:str):
alphabet =list(string.ascii_letters)
i = 0
k=0
while i < len(alphabet):
dicts = {alphabet[i]: 0}
count = something.count(alphabet[i])
dicts[i] = count
if 0 < count:
for k in dicts:
print(k)
i = i+1

Based on the code it seems like you are trying to do some sort of counter of different characters in the string?
There is no index. your "index" is the "i" iterator you are using for your while loop. This simply makes a new key in dicts as called by dicts[i]. Thus when you call the print loop, it just iterates through and reads out I as well.
Try:
dicts[alphabet[i]] = count
Also your print function only prints out the key of the dict entry instead of the key-value pair. to do that you can try:
for k in dicts:
print(k,dicts[k])
Try reading up on the python docs for dicts.
https://docs.python.org/3/tutorial/datastructures.html

Related

Find the most occurring character in a string

This piece of code is going to find the most occurring chr in a string ,and it almost works fine through a dictionary ,but unfortunately the problem is that I want to make it return the last key when there are two keys with the same frequency ,but it returns the first one.
And this is what I have done so far:
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
frequencies = {}
for items in st:
if items in frequencies:
frequencies[items] += 1
else:
frequencies[items] = 1
return max(frequencies, key=frequencies.get)
most_frequent_letter('mmmaaa')
Out[48]: 'm'
However I don't know how to return 'a' instead of 'm'.
Here's a way that creates a reverse frequency dictionary. I also made the creation of the frequency dictionary and its reverse fairly succinct by using a dictionary comprehension:
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
frequencies = {}
frequencies = {item: frequencies.setdefault(item, 0) + 1 for item in st}
rev_freq = {count: key for key, count in frequencies.items()}
return rev_freq[max(rev_freq)]
print(most_frequent_letter('nnmmmaaa')) # -> a
Python max function always returns the first maximum occurrence.
Hence, if you always want the last key, then you can just reverse the original string in your code.
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
st = st[::-1]
frequencies = {}
for items in st:
if items in frequencies:
frequencies[items] += 1
else:
frequencies[items] = 1
return max(frequencies, key=frequencies.get)
Or sort the string first if you want the lowest valued key.
You can also just create your own max function instead to suit your needs.
def most_frequent_letter(word):
letters = list(word)
return (max(set(letters), key = letters.count))
print(most_frequent_letter('mmmaaa'))
# output:m
print(most_frequent_letter('some apples are green'))
# output: e
max() will return the highest value in a list. The key argument takes a single argument function to customize the sort order, in this case, it’s letters.count. The function is applied to each item on the iterable.
letters.count is a built-in function of list. It takes an argument and will count the number of occurrences for that argument. So letters.count('m') will return 3 and letters.count(a) returns 3.
set(test) returns all the unique values from test, so {3, 3}
So what we do in this single line of code is take all the unique values of test, which is {1, 3}. Next, max will apply the list.count function to them and return the maximum value.
collections library has Counter which does the job for you: We normalize the word with lower casing and replace space before reverse string to have last appearance first.
from collections import Counter
word = 'mmmaaa'
characters = Counter(reversed(word.lower().replace(' ', '')))
# most common
print(characters.most_common(1))
yes you can get both m and a, it depends how you want to get the output but I have taken a string just for example
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
frequencies = {}
for items in st:
if items in frequencies:
frequencies[items] += 1
else:
frequencies[items] = 1
max_val=max(frequencies.values())
result=""
for key,value in frequencies.items():
if value==max_val:
result+=key
return result
result=most_frequent_letter('mmmaaa')
print(result)
the output will be "ma"
In python when you use the max function it will return the first max frequency, if you want the second max frequency you could try to delete from the list the 'm's so after that the first max frequency will be 'a'.

Populating a List - Python assigns index and gives error

I have a solution to count the number of occurrences of each letter in a string and return a dict.
def count_characters(in_str):
all_freq = {}
for i in in_str:
if i in all_freq:
all_freq[i] += 1
else:
all_freq[i] = 1
return all_freq
count_characters("Hello")
It works.
I am trying to understand how Python automatically assigns each letter as the key to the dict - its not explicitly assigned. I replace the null dictionary assignment with a list and expect to get just the frequency, without the letter.
def count_characters(in_str):
all_freq = []
for i in in_str:
if i in all_freq:
all_freq[i] += 1
else:
all_freq[i] = 1
return all_freq
count_characters("Hello")
I get an error.
TypeError: list indices must be integers or slices, not str
My question is:
How does each letter get automatically assigned as the key?
How can I return just the numbers as a list - without the letter?
How does each letter get automatically assigned as the key?
You are doing it explicitly in all_freq[i] = 1. Here, i contains a letter (though I think the variable could be named better — i typically stands for an idex of some sort, which this isn't).
How can I return just the numbers as a list - without the letter?
You could still build a dictionary and then return list(all_freq.values()). Though, if you do that, how would you know which letter each count corresponds to?
This is probably not relevant for your exercise, but the standard library already has a class for doing this sort of counting: collections.Counter.
List are indexing with integer, in your second exemple you use dictionary synthax with a list, that why python complain.
You can use count method
def count_characters(in_str):
all_freq = []
for i in in_str:
all_freq.append(in_str.count(i))
return all_freq
count_characters("Hello")
Edit : I agree with #NPE comment
You could still build a dictionary and then return list(all_freq.values()). Though, if you do that, how would you know which letter each count corresponds to?
This is probably not relevant for your exercise, but the standard library already has a class for doing this sort of counting: collections.Counter.
It's simple when we use built-in methods of dictionary like .keys(), .values()
Example:
def count_char(string):
dict = {}
count = 0
for i in string :
if i in dict.keys():
dict[i] +=1
else:
dict[i] = 1
for j in dict.values():
count += j
print(dict)
print(count)

Removing specific dictionary values inside a loop

I'm trying to make a context-free grammar simplification software.
I'm stuck when it comes to delete some specific items from the dictionary's values or even the key value pair.
The problem is that it doesn't follow a pattern.
If the element belongs to V1, I need to keep it in dictionary.
(V1 is the list of all values who derivates a terminal, those guys are the only ones I need to keep on my dictionary, but it's not that simple)
If the element doesn't belongs to V1 and dictionary's values is a string, I need to remove the element.
If the element doesn't belongs to V1 and dictionary's values is a list, I need to check if it's the single element of that list, if so, delete Value.
The failed loop is down here.
I printed the parts that I can't figure out the logic in modifying the dictionary.
counter = 0
for k,v in derivations.items():
derivationsCount = len(v)
while counter < derivationsCount:
if lista_ou_string(v[counter]): # returns True for lists, False for else
sizeOfList = len(v[counter])
counter2 = 0
while counter2 <= (sizeOfList - 1):
if v[counter][counter2] not in V1:
if derivationsCount == 1:
print("# NEED TO DELETE BOTH KEY AND VALUE FROM derivatios.items()")
else:
print("# NEED TO DELETE ONLY THE VALUE FROM derivations.items()")
counter2 += 1
else: # strings \/
if v[counter] not in V1:
if derivationsCount == 1:
print("# NEED TO DELETE BOTH KEY AND VALUE FROM derivatios.items()")
else:
print("# NEED TO DELETE ONLY THE VALUE FROM derivations.items()")
else:
print("# DO NOT DELETE ANYTHING! ALL LISTS ELEMENTS BELONGS TO 'V1'")
counter += 1
One does not want to modify a dictionary (or list) while looping over it. Therefore I create a copy of the derivations - new_derivations and modify this new_derivations:
import copy
new_derivations = copy.deepcopy(derivations)
for k, v in derivations.items():
for vi in v:
if (lista_ou_string(vi) and not set(vi).issubset(V1)) or vi not in V1:
if len(v) == 1:
# NEED TO DELETE BOTH KEY AND VALUE FROM derivatios.items()
del new_derivations[k]
break
else:
# NEED TO DELETE ONLY THE VALUE FROM derivations.items()
idx = new_derivations[k].index(vi)
del new_derivations[k][idx]
I would actually implement the above code differently: instead of thinking in terms of removing items from derivations, think instead of when an element should be added to the list. Then the code becomes much simpler:
new_derivations = {}
for k, v in derivations.items():
nv = [vi for vi in v if ((isinstance(vi, list) and set(vi).issubset(V1))
or vi in V1)]
if nv:
new_derivations[k] = nv
if you want to delete a key,value pair from a dictionary, use del:
>>> my_dictionary = {'foo':'bar', 'boo':'baz'}
>>> del my_dictionary['foo']
>>> my_dictionary
{'boo': 'baz'}
if you want to delete the value, but keep the key, you can try assigning key None:
>>> my_dictionary = {'foo':'bar', 'boo':'baz'}
>>> my_dictionary['foo'] = None
>>> my_dictionary
{'foo': None, 'boo': 'baz'}

function would not change the parameter as wanted

here is my code
def common_words(count_dict, limit):
'''
>>> k = {'you':2, 'made':1, 'me':1}
>>> common_words(k,2)
>>> k
{'you':2}
'''
new_list = list(revert_dictionary(count_dict).items())[::-1]
count_dict = {}
for number,word in new_list:
if len(count_dict) + len(word) <= limit:
for x in word:
count_dict[x] = number
print (count_dict)
def revert_dictionary(dictionary):
'''
>>> revert_dictionary({'sb':1, 'QAQ':2, 'CCC':2})
{1: ['sb'], 2: ['CCC', 'QAQ']}
'''
reverted = {}
for key,value in dictionary.items():
reverted[value] = reverted.get(value,[]) + [key]
return reverted
count_dict = {'you':2, 'made':1, 'me':1}
common_words(count_dict,2)
print (count_dict)
what i expected is to have the count_dict variable to change to {'you':2}.
It did work fine in the function's print statement, but not outside the function..
The problem, as others have already written, is that your function assigns a new empty dictionary to count_dict:
count_dict = {}
When you do this you modify the local variable count_dict, but the variable with the same name in the main part of your program continues to point to the original dictionary.
You should understand that you are allowed to modify the dictionary you passed in the function argument; just don't replace it with a new dictionary. To get your code to work without modifying anything else, you can instead delete all elements of the existing dictionary:
count_dict.clear()
This modifies the dictionary that was passed to the function, deleting all its elements-- which is what you intended. That said, if you are performing a new calculation it's usually a better idea to create a new dictionary in your function, and return it with return.
As already mentioned, the problem is that with count_dict = {} you are not changing the passed in dictionary, but you create a new one, and all subsequent changes are done on that new dictionary. The classical approach would be to just return the new dict, but it seems like you can't do that.
Alternatively, instead of adding the values to a new dictionary, you could reverse your condition and delete values from the existing dictionary. You can't use len(count_dict) in the condition, though, and have to use another variable to keep track of the elements already "added" to (or rather, not removed from) the dictionary.
def common_words(count_dict, limit):
new_list = list(revert_dictionary(count_dict).items())[::-1]
count = 0
for number,word in new_list:
if count + len(word) > limit:
for x in word:
del count_dict[x]
else:
count += len(word)
Also note that the dict returned from revert_dictionary does not have a particular order, so the line new_list = list(revert_dictionary(count_dict).items())[::-1] is not guaranteed to give you the items in any particular order, as well. You might want to add sorted here and sort by the count, but I'm not sure if you actually want that.
new_list = sorted(revert_dictionary(count_dict).items(), reverse=True)
just write
return count_dict
below
print count_dict
in function common_words()
and change
common_words(count_dict,2)
to
count_dict=common_words(count_dict,2)
So basically you need to return value from function and store that in your variable. When you are calling function and give it a parameter. It sends its copy to that function not variable itself.

Python: update dictionary key with tuple values

I have a dictionary that has keys with two values each. I need to update the second value as pass duplicate keys.
Clearly what I'm trying isn't working out.
if value1 not in dict.keys():
dict.update({key:(value1,value2)})
else:
dict.update({key:value1,+1)})
this just returned a diction with 1s for value 2 instead of incrementing by 1
The expression +1 doesn't increment anything, it's just the number 1
Also avoid using dict as a name because it's a Python built-in
Try structuring your code more like this:
my_dict = {} # some dict
my_key = # something
if my_key not in my_dict:
new_value = # some new value here
my_dict[my_key] = new_value
else:
# First calculate what should be the new value
# Here I'm doing a trivial new_value = old_value + 1, no tuples
new_value = my_dict[my_key] + 1
my_dict[my_key] = new_value
# For tuples you can e.g. increment the second element only
# Of course assuming you have at least 2 elements,
# or old_value[0] and old_value[1] will fail
old_value = my_dict[my_key] # this is a tuple
new_value = old_value[0], old_value[1] + 1
my_dict[my_key] = new_value
There may be shorter or smarter ways to do it, e.g. using the operator +=, but this snippet is written for clarity

Categories

Resources