check if value is higher in dictionary - python

Right now i have this code:
keys = {
'key1':[5],
'key2':[2],
'key3':[3],
'key4':[2],
'key5':[1],
'key6':[2],
'key7':[9],
'key8':[10],
'key9':[8],
}
for i in keys:
print(keys[i])
the last prints all the values from the list
what i want to do is only print the key and the value if the value is bigger than 5
i cant just do
if keys[i] > 5:
that doesnt work
so does anybody know how i can check and write the key and value if the value is higher than 5?

That is because the values are arrays and not numbers. When working with an array you will need to specify the index for the value you want. In your case all your arrays only have one value, so the index you want each time is 0.
You can do this to check the first item in the array, it will also print the key:
for i in keys:
if keys[i][0] > 5:
print(i, keys[i])
Here is a working example
Of course it depends what you actually want to print. If you want to print the whole array:
print(i, keys[i])
If you want to print just the first value in the array:
print(i, keys[i][0])
Personally you should review what you actually want to work with, if your values are only ever going to be single integers, then you shouldn't really be using arrays at all and should define the collection differently:
keys = {
'key1':5
}

keys[i] is returning a list of numbers, not a single number. Either change your declaration to an int:
keys = {
'key1':5...
or change the line that compares it to pick the first entry in the 'keys' list:
if keys[i][0] > 5:
if you wanted to print the key name and it's value if this returns true, you would use:
if keys[i][0] > 5:
print i, keys[i][0]

Related

I need some help using a dictionary as a function parameter

I need to replicate this same function but instead of having a list as a parameter I need a dictionary. The idea is that the calculation done by the function is done with the values, and the function returns the keys.
def funcion(dic, Sum):
Subset = []
def f(dic, i, Sum):
if i >= len(dic): return 1 if Sum == 0 else 0
count = f(dic, i + 1, Sum)
count += f(dic, i + 1, Sum - dic[i])
return count
for i, x in enumerate(dic):
if f(dic, i + 1, Sum - x) > 0:
Subset.append(x)
Sum -= x
return Subset
The function works if I enter (300, 200,100,400). But i need to use as an input something like {1:300 , 2:200 , 3:100, 4:400 }
So the calculation is done with the values, but it returns the keys that match the condition.
Im trying working with dic.keys() and dic.values() but its not working. Could you help me?
Thank u so much.
Your code isn't working with your dictionary because it's expecting to be able to index into dic with numeric indexes starting at 0 and going up to len(dic)-1. However, you've given your dictionary keys that start at 1 and go to len(dic). That means you need to change things up.
The first change is in the recursive f function, where you need the base case to trigger on i > len(dic) rather than using the >= comparison.
The next change in in the loop that calls f. Rather than using enumerate, which will generate indexes starting at 0 (and pair them with the keys of the dictionary, which is what you get when you directly iterate on it), you probably want to do something else.
Now, ideally, you'd want to iterate on dic.items(), which would give you index, value pairs just like your code expects. But depending on how the dictionary gets built, that might iterate over the values in a different order than you expect. In recent versions of Python, dictionaries maintain the order their keys were added in, so if you're creating the dictionary with {1:300, 2:200, 3:100, 4:400 }, you'll get the right order, but a mostly-equivalent dictionary like {3:100, 4:400, 1:300, 2:200 } would give its results in a different order.
So if you need to be resilient against dictionaries that don't have their keys in the right order, you probably want to directly generate the 1-len(dict) keys yourself with range, and then index to get the x value inside the loop:
for i in range(1, len(dic)+1): # Generate the keys directly from a range
x = dic[i] # and do the indexing manually.
if f(dic, i + 1, Sum - x) > 0: # The rest of the loop is the same as before.
Subset.append(x)
Sum -= x

Python 2.7: Add zeros to the size difference between lists of a multi-value dictionary and sum it

I have a multi-valued dictionary and I want to sum whatever the values are there which can be done with
for key, value in nai_dictionary.items():
nai_sum_rate.setdefault('%s' %(key), []).append(np.sum(rate_nai[key], axis=0))
for any nai_sum_rate dictionary, as suggested in this webpage. However, often times the length of the value lists is not the same.
This is the test data on which I'm testing right now
time = np.array([1,2,3,4,5,6])
test_dict['a'] = np.array([1,2,3,4,5,6]), np.array([1,2,3,4]), np.array([1,2,3,4,5,6])
What I want to do now, is to put a 0 in place of missing values for (in this case) the second array where there is no value against the time variable values and add them together.
In my previous testings, before the nai_sum_rate was a list instead of a dictionary I used the answer provided in this link to sort out the problem with the reference variable time. I've been trying with the dictionary but to no avail.
The expected sum is
3, 6, 9, 12, 10, 12
I solved the problem myself, here is the code that I came up with
for key, value in nai_dictionary.items():
i=0
while i < len(rate_nai[key]):
for key, value in nai_dictionary.items():
for index, values in enumerate(rate_nai[key]):
if len(time) < len(values):
diff = len(values) - len(time)
rate_nai[values] = values[0:np.array(values).size-diff]
elif len(time) > len(values):
diff = len(time) - len(values)
rate_nai['%s' %(key)].pop(index)
rate_nai.setdefault(
'%s' %(key)).append(np.append(np.array(values), np.zeros(diff)))
i+=1
It can tackle the problem with any number of values that have a lesser length than the reference variable time.

MemoryError using numeric range as dict index (Inefficient)

I have a need to define numeric ranges as a dictionary index such as:
SCHEDULE = {
(0, 5000): 1,
(5001, 22500): 2,
(22501, 999999999): 3
}
I search it by this function:
def range_index(table, val):
new_table = {k: v for tup, v in table.items() for k in range(tup[0], tup[1]+1)}
return new_table.get(int(val)) # int() is used to deal with floats.
which works good as long as the range isn't too big. The last entry in SCHEDULE which is 999999999 causes Python to throw MemoryError. If I decrease it to a smaller number, it's fine.
This obviously means we are building this whole table from the ranges. How can this be re-worked so that the entire ranges aren't enumerated for each search?
This is a job for an order-based data structure, not a hash-based data structure like a dict. Hashes are good for equality. They don't do range tests.
Your table should be a pair of lists. The first is sorted and represents range endpoints, and the second represents values associated with each range:
# I don't have enough information to give these better names.
endpoints = [0, 5001, 22501, 1000000000]
values = [1, 2, 3]
To find a value, perform a binary search for the index in the first list and look up the corresponding value in the second. You can use bisect for the binary search:
import bisect
def lookup(endpoints, values, key):
index = bisect.bisect_right(endpoints, key) - 1
if index < 0 or index >= len(values):
raise KeyError('{!r} is out of range'.format(key))
return values[index]
You can do a next on generator with a default value as 0 to handle StopIteration:
def range_index(table, val):
return next((v for k, v in table.items() if k[0] <= int(val) <= k[1]), 0)
This uses the usual less than, greater than checks to find the range of val and get the value corresponding.
Advantages:
No new dictionary creation for every search.
Exits immediately when the condition is satisfied.
Iterate over SCHEDULE and return the first value where val is in the associated range.
category = next(category
for (start, stop), category in SCHEDULE.items()
if val in range(start, stop + 1))
It would be a bit faster if you started off with a dict of ranges, not of tuples. It would be even faster if you made SCHEDULE into a binary tree, and did a binary search on it instead of a linear one. But this is good enough for majority of cases.
This assumes your SCHEDULE is exhaustive, and you'll get a StopIteration error if you submit a val that is not covered by any of the ranges, to signify a programmer error. If you wish an else value, put it as a second parameter to next, after wrapping the first parameter in parentheses.

How to random choose several value from a list based on the value from other list?

I have two lists and one number. list val is a list of numerical values(can have repeated value),
val = [3,2,5,6,1,6]
list pair is list of paired values(cannot have repeated value)
pair = [(1,3),(3,2),(7,3),(6,5),(3,4),(5,7)]
both list have same length, i.e., len(val) = len(pair). The number is a numeric value, say num=4.
The task is to find whether is there any value in list val are larger or equal to num, if so, find out all the maximum value and random choose one value with same index from pair. For the above example, the result should random choose a value from (6,5) or (5,7). I can write a long code with several function to finish this job. I wonder is there any concise way to do this?
num = 4
val = [3,2,5,6,1,6]
pair = [(1,3),(3,2),(7,3),(6,5),(3,4),(5,7)]
import random
print random.choice([random.choice(pair[v]) for v in range(len(val)) if val[v] == max(val)])

trying to find out places located within list

For example I am looking for a way to search every spot in a list to see where an object is located. Some example psuedocode could go:
for every column in current row:
if column is the first one:
do this
if column in the last one:
do that
else:
find the previous row and columns place
Basically I am at a standstill so any insight would be helpful thanks
EDIT Sample Code:
for row in range(0,h+1):
newrow=[]
if row==0:
newrow=[1]
elif row==1:
newrow=[1,1]
else:
for column,x in enumerate(row):
if column==0:
newrow.append(1)
elif column==len(row)-1:
newrow.append(1)
else:
newrow.append(2)
Are you looking for list.index?
l = ['foo', 'bar', 'baz']
i = l.index('bar')
# i is 1, because l[1] == 'bar'
If you need special handling based on whether it's the first or last item:
# using i from above
if i == 0:
# it's the first item
elif i == len(l) - 1:
# it's the last item
else:
# it's neither first nor last
Or if you need to process all items anyway, consider using enumerate to keep track of indices throughout the loop:
for i, x in enumerate(mylist):
if i == 0:
# x is the first item
elif i == len(mylist)-1:
# x is the last item
else:
# x is in the middle
bardockyo:
The problem appears to be that you don't have a list in row... when you run the code 'for row in range(0,h+1):', row will always be an integer with a value between greater than or equal to 0, and less than or equal to h.
Are you trying to read a file a row at a time, and keep track of the row numbers? If so, you should use a separate counter to track the row number...
I can't quite follow what you're trying to accomplish, so I can't even generate code to help you...
Added in response to bardockyo's comment:
I believe this accomplishes your goal:
# Setting h to a value so that I can use your 'range' line.
h = 5
# Create a blank dictionary object to store the row data.
rows = {}
for row_number in range(0,h+1):
row_data = []
# range isn't inclusive of the end value by default, to 'make it work', we
# must add 1 to the row_number.
for val in range(0,row_number+1):
if val == 0 or val == row_number:
# Determine if the value in 'val' is either the first number or
# last number in this row, and if so append '1' to the list.
row_data.append(1)
else:
# Determine if the value in 'val' is not the first number or last
# number in this row, and if so append '2' to the list.
row_data.append(2)
# Store the row data in the row dictionary, with the key of 'row_number'.
rows[row_number] = row_data
# Iterate through the dictionary. There's no guarantee as to the order
# returned by the 'keys()' function, so I use sorted() to ensure it's in
# numerical order.
for row_num in sorted(rows.keys()):
print 'Row Number %d contains the list:' % row_num,
for val in rows[row_num]:
print '%d' % val,
print ''
# There are better (read: cleaner) ways to format the output for printing,
# but they can be hard to read.

Categories