6
\$\begingroup\$

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)
200_success
146k22 gold badges190 silver badges479 bronze badges
asked Apr 19, 2016 at 22:31
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

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()))
answered Apr 20, 2016 at 15:57
\$\endgroup\$
4
\$\begingroup\$

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()):
answered Apr 20, 2016 at 2:26
\$\endgroup\$

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.