We have to return the frequency of the length of words in a .txt file.
E.g "My name is Emily" will be converted to a list: ["My", "name", "is", "Emily"], which I converted to a list of the lengths of each word: [2, 4, 2, 5] and then I use the function Counter which outputs a dictionary that looks like:
Counter({2: 2, 4: 1, 5: 1})
But I need it to include count of zero:
Counter({1: 0, 2: 2, 3: 0, 4: 1, 5: 1})
Any ideas?
Should I get rid of the Counter function all together?
Counter only counts the frequency of items, which means that it keeps the count of items which are present.
But, if the item you looking for is not there in the Counter object, it will return 0 by default.
For example,
print Counter()[1]
# 0
If you really need the items with zero count in it, then you can create a normal dictionary out of a Counter, like this
c = Counter({2: 2, 4: 1, 5: 1})
print {num:c[num] for num in xrange(1, max(c) + 1)}
# {1: 0, 2: 2, 3: 0, 4: 1, 5: 1}
Using the Counter class from the collections module it is indeed implicit:
txt = "My name is Emily"
d = collections.Counter([len(x) for x in txt.split()])
d variable contains the information you mentioned without the number 1:
Counter({2: 2, 4: 1, 5: 1})
d[1] returns 0
Related
sorry if this is a noob question, I wasn't able to find a solution online (maybe I just don't know what to search for).
How do I return the "found" dictionary from this recursive function
(I am only able to return the nth number)
Note: simply returning found at the end does not work for multiple reasons
# Nth Fibonacci number generator
def nth_Rfib(n, found = {0:1, 1:1}):
if n in found:
return found[n]
else:
found[n] = nth_Rfib(n-1, found) + nth_Rfib(n-2, found)
#print(found)
return found[n] # return found ** Doesn't Work **
print(nth_Rfib(5)) # 8
# instead, it should return: {0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8}
Thank you.
In both cases, you need to return found. But as your function returns dictionary, you need to access a needed value when you call it recursevly:
def nth_Rfib(n, found = {0:1, 1:1}):
if n in found:
return found
else:
found[n] = nth_Rfib(n-1, found)[n-1] + nth_Rfib(n-2, found)[n-2]
return found
print(nth_Rfib(5))
this returns:
{0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8}
Note a possible issue with default mutable arguments like your found = {0:1, 1:1}, for example:
>>> print(nth_Rfib(3))
{0: 1, 1: 1, 2: 2, 3: 3}
>>> print(nth_Rfib(5))
{0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8}
>>> print(nth_Rfib(3))
{0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8}
nth_Rfib(3) after nth_Rfib(5) returns the same dictionary, because you never reset it to the default {0:1, 1:1}.
You need a function that returns a number, so that the recursive expression
found[n] = fib(n-1) + fib(n-2)
can make sense; and you also need a function that returns a dictionary, since that's what you want to return, ultimately.
Hence it makes sense to define two distinct functions, one that returns a number, and one that returns a dict.
def nth_Rfib(n):
found = {0: 0, 1: 1}
def fib(n):
if n not in found:
found[n] = fib(n-1) + fib(n-2)
return found[n]
fib(n)
return found
This makes found a variable which is local to nth_Rfib, but acts like a global variable during the recursive calls of fib.
It also completely eliminates any oddities of mutable default arguments.
>>> nth_Rfib(10)
{0: 0, 1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8, 7: 13, 8: 21, 9: 34, 10: 55}
>>> nth_Rfib(3)
{0: 0, 1: 1, 2: 1, 3: 2}
I have two dictionaries in a program I'm writing for fun to get practice dealing with .jsons in Python. I want my program to take any player's .json file (actually pretty easy to obtain) and output how many runes of each rune type the player owns. It's basically my first week of learning about data in Python (or any language) so I'm still very new to this.
The first dictionary, I created like this:
rune_set_counts = {}
for i in range(1, 24):
rune_set_counts[i] = 0
I made the range begin with 1 because the game's .json indexes rune sets using values from 1 to 23.
The second dictionary contains 23 keys, and each key is the string that is the actual name of that particular rune type in the game. So, for example, in rune_set_counts, the first key is 1. In my second dictionary, rune_set_translated_counts, the first key is the corresponding name, "Energy".
I would like to make a function that transposes the values from the first dictionary to the second dictionary. If rune_set_counts[1] = 5, I want rune_set_translated_counts[Energy] = 5.
This was my attempt at a function:
def convert_to_rune_set(old_dict, new_dict):
for i in range(len(old_dict)):
frequency = old_dict[i+1]
new_dict[i] = frequency
The problem is, I tried that and it just added all 23 key-value pairs from the old dictionary to the new one, lol. I don't want 46 keys. How should I do this?
As #Tim Roberts mentioned in his answer, Dictionary does not have order, you will need a map of number vs their names in rune. Try something like this.
from random import randint
rune_set_counts = {}
for i in range(1, 24):
rune_set_counts[i] = randint(0, 10)
print(rune_set_counts)
# prints {1: 0, 2: 0, 3: 6, 4: 5, 5: 0, 6: 4, 7: 3, 8: 0, 9: 2, 10: 7, 11: 6, 12: 7, 13: 7, 14: 4, 15: 4, 16: 6, 17: 4, 18: 0, 19: 4, 20: 10, 21: 0, 22: 5, 23: 2}
rune_name_map = {
1: "Energy",
2: "A",
3: "B",
# And so on upto 23. You need to create this map hard-coded or read from a json
23: "V"
}
def convert_to_rune_set(count_map, name_map):
new_count_map = {}
for i in range(1, 24):
new_count_map[name_map[i]] = count_map[i]
# name_map[i] gives the name mapped to that number
return new_count_map
new_map = convert_to_rune_set(rune_set_counts, rune_name_map)
print(new_map)
#prints {'Energy': 0, 'A': 0, 'B': 6, 'C': 5, ......., 'V': 2}
If ALL you want to is swap the keys and values, that is like this:
def convert_to_rune_set(old_dict, new_dict):
for k,v in old_dict.items()
new_dict[v] = k
However, in your description, I don't understand where "Energy" comes from. Remember, dictionaries do not have "order". You can't refer to the 3rd entry in a dictionary. Perhaps you need a list of names to keep things straight?
Problem
Given a sequence (list or numpy array) of 1's and 0's how can I find the number of contiguous sub-sequences of values? I want to return a JSON-like dictionary of dictionaries.
Example
[0, 0, 1, 1, 0, 1, 1, 1, 0, 0] would return
{
0: {
1: 1,
2: 2
},
1: {
2: 1,
3: 1
}
}
Tried
This is the function I have so far
def foo(arr):
prev = arr[0]
count = 1
lengths = dict.fromkeys(arr, {})
for i in arr[1:]:
if i == prev:
count += 1
else:
if count in lengths[prev].keys():
lengths[prev][count] += 1
else:
lengths[prev][count] = 1
prev = i
count = 1
return lengths
It is outputting identical dictionaries for 0 and 1 even if their appearance in the list is different. And this function isn't picking up the last value. How can I improve and fix it? Also, does numpy offer any quicker ways to solve my problem if my data is in a numpy array? (maybe using np.where(...))
You're suffering from Ye Olde Replication Error. Let's instrument your function to show the problem, adding one line to check the object ID of each dict in the list:
lengths = dict.fromkeys(arr, {})
print(id(lengths[0]), id(lengths[1]))
Output:
140130522360928 140130522360928
{0: {2: 2, 1: 1, 3: 1}, 1: {2: 2, 1: 1, 3: 1}}
The problem is that you gave the same dict as initial value for each key. When you update either of them, you're changing the one object to which they both refer.
Replace it with an explicit loop -- not a mutable function argument -- that will create a new object for each dict entry:
for key in lengths:
lengths[key] = {}
print(id(lengths[0]), id(lengths[1]))
Output:
139872021765576 139872021765288
{0: {2: 1, 1: 1}, 1: {2: 1, 3: 1}}
Now you have separate objects.
If you want a one-liner, use a dict comprehension:
lengths = {key: {} for key in lengths}
If I have a list:
a=[6,3,2,5,1,4]
and a specific size likes 3,
so number 1~2 will tagged 1, 3~4 tagged 2, 5~6 tagged 3, likes list b:
b=[3,2,1,3,1,2]
How can I efficient to do this?
Note that list could be floating number
Sorry for unclear description,
Update with more complex example:
a=[2.5,1.4,1.6,2.1,1.5,0.7]
output will be :
b=[3,1,2,3,2,1]
This is what you need :
import math
a=[6,3,2,5,1,4]
size = 3
b = list(a)
b.sort()
for i in range(len(a)) :
w = len(b)/size #1
a[i] = math.ceil((b.index(a[i]) + 1)/(w)) #2
print(a)
1: we're getting the length of each chunk
2: we're getting in which chunk the number is present in our sorted list and replacing it with the number of the chunk in the original list
You can achieve this by first ordering the list, and splitting it into chunks of the desired size:
a=[6,3,2,5,1,4]
n = 3
a_ord = sorted(a)
def split_list(alist, wanted_parts=1):
length = len(alist)
return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts]
for i in range(wanted_parts) ]
x = split_list(a_ord,n)
And then crating a dictionary using these chunks as the bins:
d = {j:x.index(i)+1 for i in x for j in i}
print(d)
>>> {1: 1, 2: 1, 3: 2, 4: 2, 5: 3, 6: 3}
And then mapping the values using the dictionary:
b = [d[key] for key in a]
print(b)
>>> [3, 2, 1, 3, 1, 2]
sample_dict = {
1:1,
2:1,
3:2,
4:2,
5:3,
6:3
}
for k in a:
out_arr.append(sample_dict[k])
print (out_arr)
I am trying to use random.choice() to select an item from a dictionary, however, I would like one of the items to be ignored entirely. For example:
mutationMarkers = {0: "original", 1: "point_mutation", 2: "frameshift_insertion",
3: "frameshift_deletion", 4: "copy_number_addition",
5: "copy_number_subtraction"}
mutator = choice(list(markers)) # output is 0, 1, 2, 3, 4, 5
Is it possible to use random.choice and ignore {0: "original"}?
You can use a list comprehension:
mutator = choice([x for x in mutationMarkers if x != 0])
An alternative solution using set:
mutator = choice(tuple(mutationMarkers.keys() - {0}))