HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Creating a family hierarchy

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
creatingfamilyhierarchy

Problem

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)

Solution

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()):

Code Snippets

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))))
for head, (spouse, children) in sorted(data.items()):

Context

StackExchange Code Review Q#126174, answer score: 4

Revisions (0)

No revisions yet.