Requirement:
For the input list of tuples to create single line output showing father of the family|spouse|child1,child2....
Input:
input_list = [("David","Polly","Spouse"),
("Roger","Patty","Spouse"),
("David","Lily","Child"),
("Roger","Max","Child"),
("David","Sam","Child")]
Expected output:
David|Polly|Lily,Sam
Roger|Patty|Max
I have written the code but it is very clunky. Any improvement and shorter/efficient version is much appreciated.
input_list = [("David","Polly","Spouse"),
("Roger","Patty","Spouse"),
("David","Lily","Child"),
("Roger","Max","Child"),
("David","Sam","Child")]
# Expected output
'''
David|Polly|Lily,Sam
Roger|Patty|Max
'''
priority = {"Spouse" :1,"Child" :2}
intermediate_list = []
final_list =[]
return_name = ''
input_list_w_priority = [tuple(x) + (priority[x[2]],) for x in input_list ] # spouse has priority 1, children have 'lower' priority
sorted_input_list = sorted(input_list_w_priority)
get_father = sorted(list(set([ x[0] for x in sorted_input_list]))) # getting 'unique' father
for x in range(len(get_father)):
i =0
intermediate_list =[]
spouse_name =''
final_name = ''
for y in range(len(sorted_input_list)): # traversing the input list for a single father
i+=1
if(get_father[x] == sorted_input_list[y][0]):
intermediate_list.append((sorted_input_list[y][1],sorted_input_list[y][3])) # assigning spouse/child name and priority
if(i == len(sorted_input_list)):
final_tuple = sorted(intermediate_list,key=lambda x : x[1]) #sorting on priority
for z in range(len(final_tuple)):
if(final_tuple[z][1] == 1): # if spouse then pipe separated
spouse_name = '|'+ final_tuple[z][0] + '|'
else:
final_name = final_name + ','+ final_tuple[z][0]
return_name = return_name + get_father[x] + spouse_name +final_name[1:] + '\n'
print(return_name)
2 Answers 2
It looks like example for defaultdict use. No errors handling, no sorting handling at below example
from collections import defaultdict
families = defaultdict(lambda: {'Spouse': set(), 'Child': set()})
for father, person, kind in input_list:
families[father][kind].add(person)
print('\n'.join("%s|%s|%s"% (father,
','.join(families[father]['Spouse']),
','.join(families[father]['Child']))
for father in families.keys()))
Using a dictionary to group your data is arguably a better alternative to sorting, and building the actual output strings is a perfect fit for the .join()
method of strings:
data = {}
for head, tail, kind in input_list:
tails = data.setdefault(head, [None, []])
kind = kind.lower()
if kind == 'spouse' and tails[0] is None:
# Duplicate spouse entries raise, should we do differently?
tails[0] = tail
elif kind == 'child':
tails[1].append(tail)
else:
# Should wrong inputs be ignored, rather than raise?
raise ValueError('Wrong input')
for head, (spouse, children) in data.items():
print('|'.join((head, spouse, ','.join(children))))
This will print the families in some arbitrary order, but you could get them sorted by sorting the last for loop, i.e.
for head, (spouse, children) in sorted(data.items()):