1

Problem:

I have a very simple problem where I need to update the one date(either origDate or destDate) to another(either origDate or destDate) if anyone out of two is None, Empty or Non-Exists and if both of them do not exists then set both as None.

I am looking for a pythonic way to achieve this. My current code works fine but it is verbose

Example Input:

1. origin_dest_date = { 
 "originDate": "2019-06-30 23:59:00.000",
 "destDate": None
 }
2. origin_dest_date = { 
 "originDate": "2019-06-30 23:59:00.000"
 }
3. origin_dest_date = { 
 "originDate": ""
 }

Output:

1. origin_dest_date = { 
 "originDate": "2019-06-30 23:59:00.000",
 "destDate": "2019-06-30 23:59:00.000"
 }
2. origin_dest_date = { 
 "originDate": "2019-06-30 23:59:00.000",
 "destDate": "2019-06-30 23:59:00.000"
 }
  1. origin_dest_date = {
    "originDate": None, "destDate": None }

My Code:

from dateutil.parser import parse
origin_dest_date = { 
 "originDate": "2019-06-30 23:59:00.000",
 "destDate": None
 }
isoriginDate = False
isdestDate = False
if 'originDate' in origin_dest_date: 
 isoriginDate = True
 if origin_dest_date['originDate'] is not None and \
 not origin_dest_date['originDate'] == '':
 parse(origin_dest_date['originDate'])
 if origin_dest_date['originDate'] == '':
 origin_dest_date['originDate'] = None
if 'destDate' in origin_dest_date: 
 isdestDate = True 
 if origin_dest_date['destDate'] is not None and \
 not origin_dest_date['destDate'] == '':
 parse(origin_dest_date['destDate'])
 if origin_dest_date['destDate'] == '':
 origin_dest_date['destDate'] = None
if isoriginDate and not isdestDate:
 origin_dest_date['destDate'] = origin_dest_date['originDate']
elif not isoriginDate and isdestDate:
 origin_dest_date['originDate'] = origin_dest_date['destDate']
elif isoriginDate and origin_dest_date['originDate'] is None and \
 isdestDate and \
 origin_dest_date['destDate'] is not None:
 origin_dest_date['originDate'] = origin_dest_date['destDate']
elif isdestDate and \
 origin_dest_date['destDate'] is None and \
 isoriginDate and \
 origin_dest_date['originDate'] is not None:
 origin_dest_date['destDate'] = origin_dest_date['originDate']
elif not isoriginDate and not isdestDate:
 origin_dest_date['originDate'] = None
 origin_dest_date['destDate'] = None
print(origin_dest_date)
asked Sep 5, 2019 at 10:13
9
  • 1
    d = odd.get('originDate') or odd.get('destDate'); odd = {'originDate': d, 'destDate': d}...? Commented Sep 5, 2019 at 10:22
  • 2
    @deceze But then if both keys exist you'll end up overwriting one. Commented Sep 5, 2019 at 10:24
  • @deceze what is this called in Python? Commented Sep 5, 2019 at 10:26
  • @Aran I think the spec is unclear on what's supposed to happen in that case... Commented Sep 5, 2019 at 10:26
  • @deceze if both available then it should return as it is without over-writing Commented Sep 5, 2019 at 10:26

7 Answers 7

1

Two main things to improve in your code:

  • Use variables to make it look cleaner, especially the conditionals, so you don't repeatedly access the same value in the dictionary;

  • Use the dictionary get method to lookup a key - it returns its corresponding value if the key exists, if None otherwise. Then simply check if the returned value is truthy in Python, which accounts for both None and empty strings. setdefault may also be used when setting the values at the end.

This is an example of how to implement those things in order to simplify your code:

from dateutil.parser import parse
origin_dest_date = { "originDate": "2019-06-30 23:59:00.000", "destDate": None }
origin = origin_dest_date.get("originDate")
dest = origin_dest_date.get("destDate")
if origin and not dest:
 origin_dest_date["destDate"] = parse(origin)
elif not origin and dest:
 origin_dest_date["originDate"] = parse(dest)
elif not origin and not dest:
 if origin_dest_date.setdefault("originDate", None) is not None: # conditional for empty string
 origin_dest_date["originDate"] = None
 if origin_dest_date.setdefault("destDate", None) is not None: # conditional for empty string
 origin_dest_date["destDate"] = None
answered Sep 5, 2019 at 10:28
Sign up to request clarification or add additional context in comments.

3 Comments

Use if origin is not None and not dest to make a narrower condition. Otherwise you cannot distinguish between empty string and None which may or may not be what you want.
Don't you need to either parse both values or leave both of them as text?
@GiacomoAlzetta OP said to perform the same operation if the values are None or "empty", which I interpreted as being an empty string.
1

Here is my attempt:

def fill_dict(origin_dest_date, key1, key2):
 if not origin_dest_date.get(key1):
 origin_dest_date[key1] = origin_dest_date.get(key2) or None
fill_dict(origin_dest_date, 'destDate', 'originDate')
fill_dict(origin_dest_date, 'originDate', 'destDate')

The key idea is:

  1. use dict.get(key) which will return None if the key doesn't exist in the dictionary
  2. use loose if statement. Empty string or None (which is the case if the key doesn't exist in the dictionary) will resolve to False.
answered Sep 5, 2019 at 10:32

4 Comments

get(key1, None) could be shortened to get(key1)
I assumed it will raise KeyError. Thanks @ababak
There's one more: get(key2, None)
there were only two use cases when I started writing this code. I made minor change to incorporate the third use case as well.
1

Try this,

>>> def org_dest(d):
 for k,v in d.items():
 date_struc[k]=v
 if all(date_struc.values()):
 pass
 else:
 for k,v in date_struc.items():
 if not v:
 date_struc[k]= "".join([val for val in date_struc.values() if val])
 return date_struc

Final structure with default values as None which will be updated by the function.

>>> date_struc = {"originDate": None, "destDate": None}

Test:

>>> date_struc = {"originDate": None, "destDate": None}
 origin_dest_date_1 = {"originDate": "2019-06-30 23:59:00.000", "destDate": None}
>>> org_dest(origin_dest_date_1) # test-2 output
 {'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}
>>> origin_dest_date_2 = {"originDate": "2019-06-30 23:59:00.000"}
>>> org_dest(origin_dest_date_2) #test-2 output
{'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}
answered Sep 5, 2019 at 10:41

Comments

1

With a custom function and sample template dict:

def arrange_date_keys(d):
 temp = {'originDate': None, 'destDate': None} # sample dict
 if not d.get('originDate') or not d.get('destDate'):
 date_value = d.get('originDate') or d.get('destDate')
 return temp.fromkeys(temp, date_value)
 return d
origin_dest_date1 = {
 "originDate": "2019-06-30 23:59:00.000", "destDate": None
}
origin_dest_date2 = {
 "originDate": "2019-06-30 23:59:00.000"
}
origin_dest_date3 = {
 "originDate": ""
}
origin_dest_date4 = {
 "originDate": "2019-06-30 23:59:00.000", "destDate": "2019-06-30 23:59:00.000"
}
print(arrange_date_keys(origin_dest_date1))
print(arrange_date_keys(origin_dest_date2))
print(arrange_date_keys(origin_dest_date3))
print(arrange_date_keys(origin_dest_date4))

The consecutive output:

{'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}
{'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}
{'originDate': None, 'destDate': None}
{'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}
answered Sep 5, 2019 at 10:34

2 Comments

It fails when both the dates are available
@min2bro, that's really simple to fix - see my update
0

If you need this only for two static keys, that you can try this, two line of code

 must = {"originDate", "destDate"}
 test = {"originDate":"2019-06-30 23:59:00.000", "destDate": None}
 test.update({key:test[list(test.keys()-key)[0]] for key in must if key not in test or test[key] is None})

Tried with one None value :

test = {"originDate":"2019-06-30 23:59:00.000", "destDate": None} 
test.update({key:test[list(test.keys()-key)[0]] for key in must if key not in test or test[key] is None}) 
test 
{'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}

Tried with one key:

test = {"originDate":"2019-06-30 23:59:00.000",}
test.update({key:test[list(test.keys()-key)[0]] for key in must if key not in test or test[key] is None})
test
{'originDate': '2019-06-30 23:59:00.000', 'destDate': '2019-06-30 23:59:00.000'}
answered Sep 5, 2019 at 10:52

Comments

0

Update:

 try:
 if 'destDate' not in origin_dest_date:
 origin_dest_date['destDate'] = origin_dest_date['originDate']
 elif not origin_dest_date['destDate']:
 origin_dest_date['destDate'] = origin_dest_date['originDate']
 except KeyError as e:
 pass
 print(origin_dest_date)
answered Sep 5, 2019 at 10:37

Comments

0

This is the most accurate solution given by @deceze

origin_dest_date = { 
 "originDate": "2019-06-30 23:59:00.000",
 "destDate": "2019-06-30 23:58:00.000"
 }
if not origin_dest_date.get('originDate') or not origin_dest_date.get('destDate'): 
 d = (origin_dest_date.get('originDate') or None) or (origin_dest_date.get('destDate') or None)
 origin_dest_date = {'originDate': d, 'destDate': d}
print(origin_dest_date)
answered Sep 5, 2019 at 11:17

1 Comment

d = origin_dest_date.get('originDate') or origin_dest_date.get('destDate') or None is sufficient. Also, the duplicate .get calls can be avoided.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.