For a medical application I want to combine several lists into one list. The items in each list represent actions to be taken for a specific disease.
For instance the list Malaria
would look like that:
- 'Give Malaria medication'
- 'Give antibiotics'
- 'Tell patient to come back tomorrow'
- 'Give a warm lemon tea'
A second list for Bacterial sore throat
would be this:
- 'Give antibiotics'
- 'Give paracetamol'
- 'Give a warm lemon tea'
- 'Warm the patient'
The actions in each list are hierarchical. That means that the more important tasks are mentioned first.
The lists themselves have a hierarchy as well, so Malaria
is higher than Bacterial sore throat
.
I need to combine those lists into a global one, that has the items sorted in a way that both hierarchies are preserved. This would be the case that a patient has both Malaria
AND Bacterial sore throat
and receives treatment according to the importance of each action.
For this case I would want this list:
- 'Give Malaria medication' (from Malaria list because it is higher than sore throat)
- 'Give antibiotics' (covers an action from both lists)
- 'Tell patient to come back tomorrow' (from Malaria list)
- 'Give Paracetamol' (more important than warm tea as seen in
sore throat
) - 'Give a warm lemon tea' (covers an action from both lists)
- 'Warm the patient'
Currently this sorting is done by hand, but it becomes too complex with 50 diseases.
I have looked into networkx
trying to do a topological sort
but I guess this is not the right approach.
It becomes more complex when sorting is not possible and the actions are in reverse order.
For instance in Diarrhoea
there are
- make the patient drink
- give treatment
while in Severe Diarrhoea
these are in reverse order
- give treatment
- make the patient drink
In this case I want the solution to double an item in the global list to
- give treatment
- make the patient drink
- give treatment
Is there a way to solve at least one of those steps?
CodePudding user response:
In Python, you can use the
operator to append one list to the end of the other -
For the case where 2 lists are to be combined, you can add (
) them and use the index of each item in the combined list as a sorting key to dedupe -
malaria = ['give malaria medication', 'give antibiotics', 'tell patient to come back tomorrow', 'give warm lemon tea']
bacterial_sore_throat = ['give antibiotics', 'give warm lemon tea', 'warm patient']
combined_list = sorted(set(malaria bacterial_sore_throat), key=lambda x: (malaria bacterial_sore_throat).index(x))
print(*combined_list, sep='\n')
#give malaria medication
#give antibiotics
#tell patient to come back tomorrow
#give warm lemon tea
#warm patient
Note that in this case you are passing the diseases as malaria bacterial_sore_throat
when creating the combined list as malaria
ranks higher than bacterial_sore_throat
.
You can extend this logic to an arbitrary number of diseases using the itertools.chain
function to combine diseases
from itertools import chain
combined_list_2 = sorted(set(chain(malaria, bacterial_sore_throat)), key=lambda x: list(chain(malaria, bacterial_sore_throat)).index(x))
CodePudding user response:
I agree with @Corralien that once you have a DAG, topological sort is still the way to go. You just have to break the ties between elements that are at the same hierarchy level correctly. This can be done with nx.lexicographical_topological_sort
.
import networkx as nx
malaria = ['give malaria medication', 'give antibiotics', 'tell patient to come back tomorrow', 'give warm lemon tea']
bacterial_sore_throat = ['give antibiotics', 'give paracetamol', 'give warm lemon tea', 'warm patient']
edges = list(zip(malaria[:-1], malaria[1:])) list(zip(bacterial_sore_throat[:-1], bacterial_sore_throat[1:]))
graph = nx.from_edgelist(edges, nx.DiGraph)
def sort_function(item):
if item in malaria:
return '01'
elif item in bacterial_sore_throat:
return '02'
else:
raise ValueError
print(list(nx.lexicographical_topological_sort(graph, sort_function)))
# ['give malaria medication', 'give antibiotics', 'tell patient to come back tomorrow', 'give paracetamol', 'give warm lemon tea', 'warm patient']