For-loop/if -statement with character range - python

I'm creating a for loop with an if statement to append a value to a new variable if a specific condition is met. I did the same thing earlier, without the character range of i, and it worked fine. When I try the code below, it doesn't work and shoots out 'KeyError: 0', which doesn't make sense because merge_image1 is a list and not a dictionary.
Hope someone is able to help out!
behav_op1 and merge_image1 are both lists, where each element is a image file pathway (string).
This is the code that is doing the same thing, minus the character range, but for a different variable and works fine:
for i in behav_op1:
if i == 'Stimuli/Operations (Post-study)/main.png':
behav_opIdentity1.append('maintain')
elif i == 'Stimuli/Operations (Post-study)/supp.png':
behav_opIdentity1.append('suppress')
This is the code causing the issue:
for i in merge_image1:
if i[0:36] == 'Stimuli/Faces/resized_positive_faces':
image_valence1.append('positive')
elif i[0:31] == 'Sitmuli/Faces/resized_neg_faces':
image_valence.append('negative')

If I had to guess, KeyError: 0 is raised in line
if i[0:36] == 'Stimuli/Faces/resized_positive_faces':
where you're giving 0 as a key for i. if i were a String, this should probably work. However, it looks like the elements of merge_image1 aren't just Strings, but they are accessed through a key. A key generally needs to be a String itself instead of an int like 0.
The solution is to double check the type of i and access it according to its type. For instance, if i is a dict (a classical example of a container accessed by a key) consisting of a single pair, you'll need to do something like
if list(i.keys())[0][0:36] == 'Stimuli/Faces/resized_positive_faces':
or (better) use startswith suggested in the comments,
if list(i.keys())[0].startswith('Stimuli/Faces/resized_positive_faces'):
BTW if you want to check the type of i, just do
print(merge_image1[0])
If this fails because of indexing issues, then the whole code should be probably be rewritten to work with whatever merge_image1 type is.

Related

How to handle IndexError inside if statement without using try

I been having this problem in my code, that i solved and think the solution would help other people.
I have a list of objects and need to check if the objects variables are less, more, equal to other variables, the problem is that i don't always have a object in the list, so python would give an Index Error, because the list would be empty, i tried using try to catch the error but it made the code messy and hard to read.
To simplify, all i wanted was to say: if list[0].value < value2: do this, and if List Index does not exist or the condition is not True than go to else statement.
I will give the solution below and anyone else is free to give others solutions too
The way that i found to do this was, when creating the list append values that are NAN, now the list has values to be checked and if the values are NAN the answer will always be False witch leads to going to else.
I actually was using objects, so i just created a new object with all variables set to NAN.
I used numpy.nan
Couldnt you just check that the list length is greather than the index you want to check and then check the condition. Since and shortcircuts, if the list isnt long enough then the index will not get checked. this means you dont have to create dummy data especially for super long lists like in this case where i want to check index one million. This also saves you having to install and utilise other modules such as numpy
mylist = [1, 3]
index = 1_000_000
if len(mylist) > index and mylist[index] < 2:
print("yay")
else:
print("nay")

searching "key" in a dictionary

Below you will see a snippet of a code where I created a dictionary in which words from a product review are stored. Now, I am writing a function that will return the number of occurrences of the word present in the dictionary. If it isn't present, it returns 0.
(This function will be used later for another purpose. As one of the member pointed, I could use dict.get() to extract the key. however, when I tried that, I got an attribute error:'SArray' object has no attribute 'get')
Can anyone point out any obvious mistake I might have made?
Thanks in advance.
Edit:
Here is the code:
word_list=turicreate.text_analytics.count_words(products['review'])
def selected_w_count(key):
if key in word_list:
return word_list[key]
else:
return 0
selected_w_count('wise')
output ->> 0
Snapshot of the code
You have a typo in selected_w_count(key) function, if key in world_list: should be if key in word_list:.
Based on your comment that the type of word_list is an array, you may want to use word_list[0].get('wise', 0) in place of the function call. This will get the dict from the array and get key 'wise' with a default value of 0.
It seems that your code returns a turicreate.SArray object but not a standard dict object, so the get function don't work.
I search for the document and find it at:
https://apple.github.io/turicreate/docs/api/generated/turicreate.SArray.html
And maybe you can use the function turicreate.SArray.dict_trim_by_keys() to filter by the given keys and use turicreate.SArray.dict_values() to get the value, just like this:
def selected_w_count(key_word):
word_list.dict_trim_by_keys([key_word], exclude=False).dict_values() if word_list.dict_trim_by_keys([key_word], exclude=False) else 0
You can also just provide a list of key words, just change it like this:
def selected_w_count(keywords_list):
word_list.dict_trim_by_keys(keywords_list, exclude=False).dict_values() if word_list.dict_trim_by_keys(keywords_list, exclude=False) else 0
The documents of these functions are here:
https://apple.github.io/turicreate/docs/api/generated/turicreate.SArray.dict_trim_by_keys.html
https://apple.github.io/turicreate/docs/api/generated/turicreate.SArray.dict_values.html
Take care that the true result will also return A SArray of list type but not just a num.
Not sure whether it works, hope it can help you.

How to get result from a dictionary with lists as the values

I have a JSON file with n number of dictionaries as listed below in the snippet. I am trying to fetch the value against the key but it fails in my code when the value is defined as a list like in the below example for key affected_packages. I tried to check why my code fails, so it looks like it pulls no data out of it this fails. I just see two brackets [] as output instead of "thunderbird-0:78.9.1-1.el8_1","thunderbird-0:78.9.1-1.el8_2","thunderbird-0:78.9.1-1.el8_3","thunderbird-0:78.9.1-1.el7_9"
{"bugzilla_description":"CVE-2021-23992 Mozilla: A crafted OpenPGP key with an invalid user ID could be used to confuse the user","cvss_score":null,"cvss_scoring_vector":null,"CWE":"CWE-347","affected_packages":["thunderbird-0:78.9.1-1.el8_1","thunderbird-0:78.9.1-1.el8_2","thunderbird-0:78.9.1-1.el8_3","thunderbird-0:78.9.1-1.el7_9"],"resource_url":"https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2021-23992.json","cvss3_scoring_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L","cvss3_score":"4.3"}
I am doing like below in my code as I need to prepare a worksheet. Sample snippet:
for i in range(offs):
ws.cell(row=r+1+i,column=2).value = v['current'][i]
if 'affected_packages' in list(tmp1.keys()):
ws.cell(row=r+1+index1,column=11).value = tmp1['affected_packages']
print("affected_packages done")
if 'advisories' in list(tmp1.keys()):
ws.cell(row=r+1+index2,column=13).value = tmp1['advisories']
print("advisories done")
Is there a way I can pull the value correctly for those defined as a list in the dictionary? I need a way so that it won't hamper my existing logic to pull value for normal key: value since while looking up into my JSON file.
So need something which can fulfil both whether my value in the dictionary is as a list or not as a list and I can get value against the keys in my json file.
As mentioned in the other answers, you can test the type of a variable using
if type(some_variable) == list:
# do what you need to do
You do mention that your code breaks, and I guess it's because inserting into a cell expects a String, not the list you pass in the line
ws.cell(row=r+1+index1,column=11).value = tmp1['affected_packages']
So how do we get a string out of a list of strings? It's pretty easy using the join method.
my_list = ["thunderbird-0:78.9.1-1.el8_1","thunderbird-0:78.9.1-1.el8_2","thunderbird-0:78.9.1-1.el8_3","thunderbird-0:78.9.1-1.el7_9"]
as_one_string = ", ".join(my_list)
print(as_one_string)
# Prints out 'thunderbird-0:78.9.1-1.el8_1, thunderbird-0:78.9.1-1.el8_2, thunderbird-0:78.9.1-1.el8_3, thunderbird-0:78.9.1-1.el7_9'
So combining the two ideas:
if 'affected_packages' in list(tmp1.keys()):
ws.cell(row=r+1+index1,column=11).value = tmp1['affected_packages'] if type(tmp1['affected_packages']) != list else ", ".join(tmp1['affected_packages'])
print("affected_packages done")
Quick feedback because I can't comment yet: Please always include an error message and/or the output you get when running your code when you ask a question
If I understand it correctly, you just need to determine if a value in dict is list. You can do that as below:
for i in d.items(): # gets key, value as a tuple.
if isinstance(i[1],list):
print('its a list, process it accordingly')
else:
print('Not a list')
Regarding your second problem, when you don't know if it is a list or something else, you can just check the type, maybe like this:
if type(tmp1['affected_packages']) == list:
# process the list
else:
# process other types
Since you don't know the data type, having this explicit type check seems necessary.

Getting inaccurate response.corr in Psychopy

I use psychopy2 v1.85.2 for my experiment in Mac. I have gotten a message after an experiment as follows and then have some trouble in inaccurate response.corr though getting an accurate response.keys in excel. Please tell me how to get accurate response.corr.
FutureWarning:elementwise comparison failed;returning scalar
instead,but in the future will perform elementwise comparison
if (response0.keys == str(correctAns0) or (response0.keys == correctAns0):
response0.keys will return a list, even if it contains just a single value. This is why it is named .keys rather than .key. e.g. if the subject pushed the 'a' key, the results would be the single element list ['a'].
You should treat it as a list and make comparisons like yours to a specified single item within that list. e.g.
# test against the zeroth list item rather than the entire list:
if response0.keys[0] == str(correctAns0): # etc

Assign a Range of Numbers to a Single Key with Dictionaries

I was working on a dictionary, but I came up with an issue. And the issue is, I want to be able to use more than 1 number in order to reference a key in a dictionary.
For example, I want the range of numbers between 1 and 5 to be all assigned to, let's say, "apple". So I came up with this:
my_dict['apple'] = range(1,5)
At the program's current state, its far from being able to run, so testing is an issue, but I do not receive any issues from my editor. I was just wondering, is this the correct way to go about this? Or is there a better way?
Thanks.
EDIT:
A little more info: I want to make a random integer with the randint function. Then, after Python has generated that number, I want to use it to call for the key assigned to the value of the random integer. Thing is, I want to make some things more common than others, so I want to make the range of numbers I can call it with larger so the chance of the key coming up becomes likelier. Sorry if it doesn't make much sense, but at the current state, I really don't even have code to show what I'm trying to accomplish.
You have the dictionary backwards. If you want to be able to recall, e.g., 'apple' with any of the numbers 1-5, you'd need the numbers to be the keys, not the values.
for i in range(1,6): # range(a,b) gives [a,b)
my_dict[i] = 'apple'
etc. Then, my_dict[4] == 'apple' and the same is true for the other values in the range.
This can create very large dictionaries with many copies of the same value.
Alternately, you can use range objects as dictionary keys, but the testing will be a bit more cumbersome unless you create your own class.
my_dict[range(1,6)] = 'apple'
n = random.randint(1, 5)
for key in my_dict:
if n in key:
print(my_dict[key])
...prints apple.
The value in a dictionary can be any arbitrary object. Whether it makes sense to use a given type or structure as a value only makes sense in the context of the complete script, so it is impossible to tell you whether it is the correct solution with the given information.

Categories

Resources