Reputation: 45
So I have recently started using prolog, since I am getting into using AI and FOL. I have noticed quite a few differences with other languages I have used such as Python and Java and I am having a difficult time trying to "compare" these languages.
The main problem I am having is that I have no idea how to build a rule to get a list of the second item of the tuples in a list.
The input is a list of tuples, for example: [(1,aa),(2,bb),(3,cc),(4,dd)]
.
I am trying to write a function such that the output is a LIST OF SECOND ITEM OF EVERY TUPLE within the list, namely [aa, bb, cc, dd]
I have already tried doing something along the lines of "extract_second_item([(1,aa),(2,bb),(3,cc),(4,dd)], [(_ , output)|_])
". But when I run that function, it only returns the second item of the first tuple (aa
) but apparently not the rest.
Thanks!
Upvotes: 1
Views: 727
Reputation: 60024
Actually, a tuple is a compound:
?- write_canonical((a,b,c)).
','(a,','(b,c))
true.
so arg/3 is pretty functional to extract the second argument by position from a tuple:
?- arg(2,(a,b),X).
X = b.
the you can solve your problem in a compact way, using a lambda expression
?- maplist([X,Y]>>arg(2,X,Y), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
Tuples aren't widely used in Prolog, indeed the problem has a simpler solution, directly applying pattern matching:
?- maplist([X,Y]>>(X=(_,Y)), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
Pattern matching could be pushed in the lambda arguments:
?- maplist([(_,Y),Y]>>true, [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
Instead of library(yall), you could choose library(lambda), trading speed for portability:
?- use_module(library(lambda)).
true.
?- maplist(\X^Y^(X=(_,Y)), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
In SWI-Prolog, this requires you install pack(lambda),
?- pack_install(lambda).
Upvotes: 2
Reputation: 12972
You need to use simple recursion:
extract_second_item([], []).
extract_second_item([(_,X)|T], [X|T2]):- extract_second_item(T,T2).
Now querying:
?- extract_second_item([(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
Another great way proposed by @lurker is to use maplist/3
:
Firstly we define a simple predicate that returns the second item from a tuple:
second_item((_,X), X).
Then we map second_item/2 to each tuple in the list using maplist/3
:
?-maplist(second_item, [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].
Upvotes: 3