'if' 'or'- statement in dictionary always returns TRUE - python-3.x

I have this python dictionary:
event_dict = {
'False': 1,
'Hit': 2,
'MP1': 3,
'MP2': 4,
'MP3': 5,
'M_False': 6,
'M_Hit': 7,
'OGT': 8,
'PMC': 9,
'S 4': 10,
'actiCAP Data On': 11,
'boundary': 12
}
And I wrote this code to check if the entries "TriEVE", "TriODD", "TriPMC" are in the dictionary (They're not!):
if "TriEVE" or "TriODD" or "TriPMC" in event_dict:
print('THIS SESSION HAS BAD ANNOTATIONS!!!!!!!')
The code returns:
THIS SESSION HAS BAD ANNOTATIONS!!!!!!!
I tried to use the 'if'-statement with just one input (without 'or'), like:
if "TriEVE" in event_dict:
print('THIS SESSION HAS BAD ANNOTATIONS!!!!!!!')
print(subject)
The code returns nothing, as expected.
Why can't I use 'or'-statements in this case? Is there a smarter way of searching for more than one dictionary entry at once?

In this case, you want
if "TriEVE" in event_dict.keys() or "TriODD" in event_dict.keys() or "TriPMC" in event_dict.keys():
this is because anything not-zero or non-None is evaluated to True in Python
Since it seems that you wanted to search the keys of the dict, you have to use .keys() or .values() if you want to look at values. The object itself isn't useful in this context

Related

can't remove some duplicate elements from a list in python

well I was trying to remove duplicate items from a list so it has unique items and I also wanted to use for and if my code went so well but in one condition I faced something I don't understand. this is the example :
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a:
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
print(a)
[1, 21, 21, 16, 20, 7]
I don't understand why !! It removes 2,3,28 which was predicted but not 21 !
any help would be great , thanks.
The best solution for this case is using set(). If you do list(set(a)) it will remove all duplicates.
Notice that set() is not the same as list() so be sure to turn it back to a list if you want to keep using list methods.
About your code, the problem with your code is that you're running on the list as you're changing it.
While you run over the items the indexes changes and that's why you miss some of the items.
You can see more clearly what happens if you add a print to understand what's x's value:
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a:
print(x)
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
I believe your issue is that you are changing the list while you're looping over it
Try using a.copy() to create a new copy of the list to loop over like so.
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a.copy():
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
print(a)
This code will output
[1, 16, 20, 7]

remove field from response output in python

Can any suggest how to remove field EventTime from below output in python3 using boto3 .
'Events': [{
'EventId': '4a9f4c8e-3394-41df-xxxx-7e725b7c728e',
'EventName': 'ConsoleLogin',
'ReadOnly': 'false',
'EventTime': datetime.datetime(2018, 11, 5, 9, 49, 19, tzinfo = tzlocal()),
'EventSource': 'signin.amazonaws.com',
'Username': 'tests.sde',
'Resources': [],
'CloudTrailEvent': '{"eventVersion":"1.05","userIdentity":
The response syntax above is just a standard python dictionary. The one complication with the boto3 response syntax is the Events key is really a dictionary wrapped in a list, but you can still use pop() to remove the EventTime key from that dictionary. In the example below I've named the output response.
response['Events'][0].pop('EventTime', None)
print(response)
pop() removes keys in-place so after you run the code and look at response the EventTime key will be removed.
This is a simple python element deletion from a dictionary. In your case you have a list of dictionaries. If you want to delete EventTime in all the dictionaries that are in the 'Events':[{}]. you can use the below code:
for event in response['Events']:
try:
del event['EventTime']
except KeyError:
print("Key 'EventTime' is not found")
The above code will delete the 'EventTime' and throws an error if it doesn't find any element with key EventTime. In your case, I guess all the dictionaries will have it.

Deleting Dictionaries Keys with a For If Statement in Python 3

I feel very dumb asking this. How do I delete a keys in a dictionary with an if statement that references the values. When I do this:
newdict = {"a":1,"b":2,"c":3}
for (key,value) in newdict:
if value == 2:
del newdict[key]
print(newdict)
It throws this error:
line 3, in <module>
for (key,value) in newdict:
ValueError: not enough values to unpack (expected 2, got 1)
Thank you.
If you need to delete based on the items value, use the items() method or it'll give ValueError. But remember if you do so it'll give a RuntimeError. This happens because newdict.items() returns an iterator not a list. So, Convert newdict.items() to a list and it should work. Change a bit of above code like following -
for key,value in list(newdict.items()):
if value == 2:
del newdict[key]
output -
{'a': 1, 'c': 3}

Returning a list of N dictionary keys that have the maximum integer values

my_dict = {'label': 6, 'label_2': 5, 'label_3': 9, 'label_4': 12}
I would like to create a list that will contain the top 2 (or 3, or 4, or 50... this will vary) dictionary keys, according to their highest values. So in the example above if I wanted the top 2, I should get:
['label_3', 'label_4']
for top 3 I should get:
['label', 'label_3', 'label_4']
And so on.
After reading some other stackoverflow threads, I've been experimenting with heapq, but can't get it to work the way I want. Would appreciate some help.
Of course, the moment I post here, I find a solution (thanks to the heapq documentation). This works:
my_list = heapq.nlargest(3, my_dict, key=my_dict.get)
This will go over my_dict and return the keys with the 3 largest values.
Thanks.

Python3.4 Dictionary value replacement issue

I have some code which takes a list of dictionaries and creates another list of dictionaries.
Each dictionary in the list has two key/value pairs "ID" and "opcode", where "opcode" is a 32 bit number.
My code needs to create a second list of dictionaries where the opcodes are separated, i.e. a dictionary with opcode=5 would become two dictionaries with opcode=1 and opcode=4.
(opcode is a 32 bit number and my requirement is that only 1 bit is high, ie opcode=1,2,4,8,16 etc)
I've simplified the problem into the following; my code needs to turn this:
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
into this:
part_=[{"ID":1,"opcode":4},{"ID":2,"opcode":1},{"ID":2,"opcode":4},{"ID":3,"opcode":2},{"ID":3,"opcode":4}]
Currently my code is the following
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
The output of the code is:
{'opcode': 4, 'ID': 1}
{'opcode': 1, 'ID': 2}
{'opcode': 2, 'ID': 3}
Interestingly if I modify the code slightly so that the value modification line is not there, the extra dictionaries are created, but obviously the opcode is not correct.
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
#part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
The output is
{'ID': 1, 'opcode': 4}
{'ID': 2, 'opcode': 5}
{'ID': 2, 'opcode': 5}
{'ID': 3, 'opcode': 6}
{'ID': 3, 'opcode': 6}
I can get around the issue by going about the problem a different way, but in the interest in learning what is going on I'm out of my depth.
This is caused as when you append i to the new list you do not create a copy of the dictionary instead you add a reference to the original dictionary. This means that when you change the dictionary in the next line you also change value in part. This causes the loop not to match the any more parts of the opcode. You can see this if you print out the values of part at the end of your code.
The python documentation explains this as:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
Reference
You can fix this by creating a copy of the dictionary when you append it. This will allow you change the value without affecting the original dictionary. Python allows you to copy objects using the copy module (Documentation).
Just import copy and then do part_.append(copy.copy(i)) instead of part_.append(i).
import copy
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part = [{"ID": 1, "opcode": 4}, {"ID": 2, "opcode": 5}, {"ID": 3, "opcode": 6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(copy.copy(i))
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)

Resources