I am retrieving multiple lists from lists and put them into a new list. But I want to make the new list of individual items and not a list with lists. So say I have the list [[a,b],c,[d,e]] I would like to get [a,b,c,d,e]. How do I go about this?
-
1Use [`flatten/2`](https://www.swi-prolog.org/pldoc/doc_for?object=flatten/2) – gusbro Nov 19 '20 at 17:08
-
Its for school and I am not allowed to use flatten lol – Coderman Nov 19 '20 at 17:11
-
Then you should tell us what have you tried and where are you stuck – gusbro Nov 19 '20 at 19:50
2 Answers
To use an example code snipping from a random question today: assume you have a knowledge base as follows:
step('pancakes', 1, 'mix butter and sugar in a bowl', [butter, sugar], [bowl]).
step('pancakes', 2, 'add eggs', [eggs], []).
step('pancakes', 3, 'mix flour and bakingpowder', [flour, bakingpowder], []).
And you are interested in all the ingredients for a dish. First idea would be
?- Dish='pancakes', findall(X,step(Dish,_,_,X,_),I).
Dish = pancakes,
I = [[butter, sugar], [eggs], [flour, bakingpowder]] ;
false.
But the problem here is that the ingredients list is nestet. Since flatten/2
is not allowed you now have 2 choices: either flattening your result or to use findall over all ingredients from the ingredientslist of each step
for a dish.
For flatten I recomment using the implementation flatten2/2
from this post. The resulting question could be something like this:
?- Dish='pancakes', findall(X,step(Dish,_,_,X,_),I), flatten2(I,J).
Add a sort/2
if you want to get rid of duplicates as statet in this post.
If you want to use the second method, you have to create a helper predicate which shows the ingredients for all dishes. ingredients/3
gives the ingredients as single element for each dish and step number. So for each Dish
and Step
multiple entries with different Ingredients are possible.
ingredients(Dish,Step,Ingred):-
step(Dish,Step,_,L,_),
member(Ingred,L).
?- Dish='pancakes', findall(X,ingredients(Dish,_,X),I).
Dish = pancakes,
I = [butter, sugar, eggs, flour, bakingpowder] ;
false.
To get rid of the duplicates use sort/2
.
PS: I still don't know if you are allowed to use findall/3
.

- 3,718
- 4
- 16
- 36
flatten(SOURCEs,TARGETs)
:-
phrase(flatten(SOURCEs),TARGETs)
.
flatten([HEAD|TAILs]) --> { is_list(HEAD) } , HEAD , flatten(TAILs) .
flatten([HEAD|TAILs]) --> { \+ is_list(HEAD) } , [HEAD] , flatten(TAILs) .
flatten([]) --> [] .
/**
?- flatten([[a,b],c,[d,e]],TARGETs) .
TARGETs = [a, b, c, d, e] ;
false.
?-

- 763
- 5
- 9