Pass None or empty value to dictionary key if result from result comprehension is nothing - list-comprehension

How to pass None or empty value to failure_dict['Failure Reason'] if failure reason has no value.
failure_dict['Failure Reason'] = ', '.join(
[failure_reason for failure_reason in self.get_failure_reason(summary_content) if failure_reason])

What I understand is that you want the list in join() to contain an empty value if self.get_failure_reason returns an empty value. You can't have None since join() will only work with a list of strings. For that:
failure_dict['Failure Reason'] = ', '.join(
[failure_reason for failure_reason in self.get_failure_reason(summary_content)
if failure_reason else ''])
If what you want to do is give failure_dict['Failure Reason'] a None value if any of the return values of self.get_failure_reason is empty, you'll have to open up the for loop:
return_list = []
flag = 1
for failure_reason in self.get_failure_reason(summary_content):
if failure_reason:
return_list.append(failure_reason)
else:
flag = 0
break
if flag:
failure_dict['Failure Reason'] = ', '.join(return_list)
else:
failure_dict['Failure Reason'] = None

Related

Python: Subclassing a dict to have two keys and a defaultvalue

following the two very readable tutorials 1 and 2, I would like to create a dictionary with two keys that gives a defaultvalue in case the key-pair does not exist.
I managed two fullfill the first condition with
from collections import defaultdict
class DictX(dict):
def __getattr__(self, key1 = None, key2 = None):
try:
return self[(key1,key2)]
# This in idea of how to implement the defaultdict. But it does not seem to work
# except KeyError as k::
# self[(key1,key2)] = 0.
# return self[(key1,key2)]
## or just return 0
except KeyError as k:
raise AttributeError(k)
def __setattr__(self, key1, key2, value):
self[(key1,key2)] = value
def __delattr__(self, key):
try:
del self[key]
except KeyError as k:
raise AttributeError(k)
def __repr__(self):
return '<DictX ' + dict.__repr__(self) + '>'
sampledict = DictX()
sampledict[3,5] = 5
sampledict[1,4] = 4
print("Checking the dict ",sampledict[1,4])
# This line is going to throw an error
print("Checking the default dict ",sampledict[3,6])
How do I code the defaultvalue behaviour?
Pro-Question:
If I just give one value sampledict[1,] or sampledict[1,:], I would like to get a list of all key - value pairs that start with 1. Is that possible?

Is there a way in which I can iterate over a dictionary and use it in a while loop?

This is how my code looks in python. in the line where df = get_data_df(id,start_at) , instead of defining id one by one, I would like for my program to iterate over id and use it in the program below. please help me with how to iterate over the dictionary (id) and use it in the while loop.
id= {'O': 6232,
'S': 5819,
'S': 5759,
'R': 6056,
'M': 6145,}
whole_df = pd.DataFrame()
start_at = int(datetime(2020,8,1,6,0,0,0, pytz.UTC).timestamp() * 1e6)
while True:
df = get_data_df(id,start_at)
if df.shape[0] <= 1:
break
else:
whole_df = whole_df.append(df)
last_timestamp = whole_df.last_valid_index().timestamp()
start_at = int(last_timestamp * 1e6)
#print(whole_df)
for key in id:
print(key)
Is one way you could do it. Or you Could do it this way
i = 0
while True:
list(id)[i]
i += 1
By Just itterating a index and grabbing a value at each point from that Index
There a multiple ways of iterating over a python dictionary using a for loop:
for key in your_dict:
value = your_dict[key]
print(value)
for value in your_dict.values():
print(value)
for key, value in your_dict.items():
print(key, '=', value)
If you realy want a while loop:
keys = your_dict.keys()
i = 0
while i < len(keys):
value = your_dict[keys[i]]
print(key, '=', value)

Finding the minimum value from a tuple list

I'm new to coding and need to find the minimum value from a list of tuples.
def min_steps(step_records):
""" random """
if step_records != []:
for steps in step_records:
day, step = steps
result = min(step)
else:
result = None
return result
This results in an error:
'int' object is not iterable
How do I return the min if the list is something like this?
step_records = [('2010-01-01',1),
('2010-01-02',2),
('2010-01-03',3)]
tuples can be indexed (see: Accessing a value in a tuple that is in a list).
Using that we can create a list from those indices and call minimum like you had done:
def min_steps(step_records):
""" random """
if step_records:
result = min([step[1] for step in step_records]) # min([1,2,3])
else:
result = None
return result
step_records = [('2010-01-01',1),
('2010-01-02',2),
('2010-01-03',3)]
print(min_steps(step_records))
output:
1

How to convert strings in a list to floats

I have this list:
array = ['Katherine', '999', '333']
I need to convert the '999' and '333' into floats.
The list should look like this after:
array = ['Katherine', 999.0, 333.0]
Yeah, float(s) can do this. Here is the code.
array = ['Katherine', '999', '333']
def is_number(s):
""" Returns True if the string is a number. """
try:
float(s)
return True
except ValueError:
return False
print(array)
// for i, v in enumerate(array):
// if is_number(v):
// array[i] = float(v)
array = list(map(is_number, array))
print(array)

Global Name "msg" not defined

I'm currently writing a class called SMS_store(). In it, I have a method called delete.
Delete is simply supposed to make sure the user has given me a valid integer. If so, it's supposed to pop an item from the list.
class SMS_store():
def __init__(self):
self.__inbox = []
def delete(self, i):
if i >= len(self.__inbox):
return None
else:
self.__inbox.pop[i]
Whenever I run the code in my test program, I run into two errors at my delete stage:
1) if I type myInbox.delete(2) when there's only 2 items in the list, I get "list index out of range" and I though I was protected from that error. myInbox.delete(3) gives me None.
2) If I type myInbox.delete(1) when there's a valid index 1 in my list, it says global name 'msg' not defined. I don't get why I'm seeing that error.
Here's my full class code.
#SMS_store class
"""
Pre-condition: SMS_store class is instantiated in client code.
Post-condition: SMS_store class is instantiated.
"""
class SMS_store():
#Object instantiation
"""
Pre-conditon: SMS_store class is instantiated in client code.
Post-condition: Object creates an empty list.
"""
def __init__(self):
self.__inbox = []
#add_new_arrival method
"""
Pre-condition: Class method is handed a valid phone number of 11, 10, or 7
digits as a string with no hyphens or letters, a string containing a time,
and a string containing the text of a message.
Post-condition: Method will append a tuple containing False for an
undread message, the phone number, the time arrived and the text of the
message to the class created list.
"""
def add_new_arrival(self, from_number, time_arrived, text_of_SMS):
number = from_number
#Check for valid phone number and add hyphens based on number length
if len(number) == 11:
number = number[0] + "-" + number[1:4] + "-" + number[4:7] + "-"\
+ number[7:]
elif len(number) == 7:
number = number[:3] + "-" + number[3:]
elif len(number) == 10:
number = "1-" + number[:3] + "-" + number[3:6] + "-" + number[6:]
elif number.isalpha():
number = "Invalid number"
else:
number = "Invalid number"
time = time_arrived
text = text_of_SMS
message = (False, number, time, text)
self.__inbox.append(message)
#message_count method
"""
Post-condition: method returns the number of tuples in class created list.
Returns None if list is empty.
"""
def message_count(self):
count = len(self.__inbox)
if count == 0:
return None
else:
return count
#get_unread_indexes method
"""
Post-condition: method creates an empty list,checks for any tuples with
"False" at index 0. If "False" is found, it appends the index for the
tuple in the list. Method returns list of indexes.
"""
def get_unread_indexes(self):
unread = []
for message in self.__inbox:
if message[0] == False:
unread.append(self.__inbox.index(message))
return unread
#get_message method
"""
Pre-condition: Method is passed an integer.
Post-condition: Method checks for a valid index number. If valid, the
method will then check if indexed tuple contains "True" or "False" at index
0. If True, message is returned in new tuple containing items from indexes
1, 2, and 3. If False, a new tuple is created containing "True"
indicating the message is now read, plus indexes 1, 2, and 3 from the
original called tuple.
"""
def get_message(self, i):
#check for valid index number
if i >= len(self.__inbox):
return None
else:
msg = self.__inbox[i]
if msg[0] == True:
return (msg[1], msg[2], msg[3])
#create new tuple with True, and index 1-3 from original tuple
else:
self.__inbox.pop(i)
newMsg = (True, msg[1], msg[2], msg[3])
self.__inbox.insert(i, newMsg)
return newMsg[1:]
#delete method
"""
Pre-condition: Method is passed an integer.
Post-condition: Method checks that the integer is a valid index number. If
valid, method pops index from class created list.
"""
def delete(self, i):
if i >= len(self.__inbox):
return None
else:
self.__inbox.pop(i)
#Clear method
"""
Post-condition: method resets the inbox to an empty list.
"""
def clear(self):
self.__inbox = []
Here's how I am using the code in my test program:
#Test instantiation
naomisInbox = SMS_store()
martisInbox = SMS_store()
#Test add_new_arrival
naomisInbox.add_new_arrival("12345678912", "10:38PM", "Yay! Sorry, been")
martisInbox.add_new_arrival("23456789123", "10:37PM", "Hey I finally hit 90")
martisInbox.add_new_arrival("12345678912", "10:40PM", "Now I sleep :)")
naomisInbox.add_new_arrival("23456789123", "10:40PM", "Night")
#Test message_count
count = naomisInbox.message_count()
print("Naomi has", count, "messages in her inbox.")
count = martisInbox.message_count()
print("Marti has", count, "messages in his inbox.\n")
#Test get_unread_indexes
numUnread = naomisInbox.get_unread_indexes()
print("Naomi has unread messages at indexes: ", numUnread)
numUnread = martisInbox.get_unread_indexes()
print("Marti has unread messages at indexes: ", numUnread,"\n")
#Test get_message
msg = naomisInbox.get_message(9)
print("Getting message from Naomi's inbox at index [9]: ")
if msg == None:
print("No message at that index.")
else:
for item in msg:
print(item)
print("\n")
numUnread = naomisInbox.get_unread_indexes()
print("Naomi now has unread messages at indexes: ", numUnread, "\n")
msg = martisInbox.get_message(1)
print("Getting message from Marti's inbox at index [1]:")
for item in msg:
print(item)
print("\n")
numUnread = martisInbox.get_unread_indexes()
print("Marti now has unread messages at indexes: ", numUnread, "\n")
#Test delete
remove = naomisInbox.delete(0)
if remove == None:
print("Invalid index.")
count = naomisInbox.message_count()
numUnread = naomisInbox.get_unread_indexes()
print("Naomi now has", count, "messages with unread messages at index: ",\
numUnread)
#Test clear
print("\nAfter clearing: ")
naomisInbox.clear()
count = naomisInbox.message_count()
print("Naomi now has", count, "messages in her inbox.")
martisInbox.clear()
count = martisInbox.message_count()
print("Marti now has", count, "messages in his inbox.")
Error
Error:
Traceback (most recent call last):
File "/home/theriddler/Documents/CSIS153/Assignments/Nansen3/Nansen3.py", line 56, in <module>
remove = naomisInbox.delete(0)
File "/home/theriddler/Documents/CSIS153/Assignments/Nansen3/modSMS.py", line 125, in delete
NameError: global name 'msg' is not defined
Any help is appreciated. Sorry if it's a repeated question. Thanks, Blackwell.
for your first problem.
1)if there are only two items in the list then you cannot delete the 2nd item by passing 2 as index it should be 1.
2)your second problem tells that you are using same msg variable in SMS_store class within different functions without defining it as self variable for the class. However cant find any thing for now. You should probably check it again as it works well on my machine.
Now a little more light on your delete method:
def delete(self, i):
if i >= len(self.__inbox):
return None
else:
self.__inbox.pop(i)
Here if you want to delete the last message always then just use self.__ibox.pop() without passing any index but in case you want to delete an indexed message then u should do self.__ibox.pop(i-1)
because in case i is last element of the list then it will always be equal to length of the list and else will never be executed.
Also your delete method returns None only in if condition but if else runs then again None is returned by default so
remove = naomisInbox.delete(0)
if remove == None:
print("Invalid index.")
This will always print 'invalid index' as message even if the message gets deleted.

Resources