Dennis Vash
Dennis Vash

Reputation: 53884

How to extract data to list in Prolog?

I have an array L of some type, I'm trying to extract the data to an array, for example:

L=[day(sunday),day(monday)]

to

Target=[sunday,monday]

Tried using forall and searched for related questions on Prolog lists.

extract_data_to_list(L,Target) :-
    member(day(Day),L),
    length(L, L1),
    length(Target, L1),
    member(Day,Target).

Current output:

?- extract_data_to_list([day(sunday),day(monday)],Target).
Target = [sunday, _5448] ;
Target = [_5442, sunday] ;
Target = [monday, _5448] ;
Target = [_5442, monday].

Desired output:

?- extract_data_to_list([day(sunday),day(monday)],Target).
Target=[sunday,monday]

Upvotes: 4

Views: 1263

Answers (3)

false
false

Reputation: 10102

This is an ideal problem for library(lambda) for SICStus|SWI:

maplist(\day(N)^N^true, Dates, Daylist).

Upvotes: 3

Daniel Lyons
Daniel Lyons

Reputation: 22803

I have a couple other ways you can do this, just in case you're wondering.

?- findall(D, member(day(D), [day(monday), day(tuesday)]), Days).
Days = [monday, tuesday].

The trick here is that you can use findall/3 to drive a simple loop, if the Goal (argument 2) uses member/2. In this case, we're unifying day(D) with each item in the list; no further work really needs to happen besides the unification, so we're able to "tear off the wrapping" just with member/2 but you could drive a more complex loop here by parenthesizing the arguments. Suppose you wanted to change day to day-of-week, for instance:

?- findall(DoW, (member(day(D), 
                 [day(monday), day(tuesday)]), DoW=day_of_week(D)), 
           Days).
Days = [day_of_week(monday), day_of_week(tuesday)].

Making the goal more complex works, in other words, as long as you parenthesize it.

The second trick is specific to SWI-Prolog (or Logtalk, if you can use that), which is the new library(yall):

?- maplist([Wrapped,Day]>>(Wrapped=day(Day)),
          [day(monday),day(tuesday)], X).
X = [monday, tuesday].

library(yall) enables you to write anonymous predicates. [Wrapped,Day]>>(Wrapped=day(Day)) is sort of like an inline predicate, doing here exactly what @lurker's day_name/2 predicate is doing, except right inside the maplist/3 call itself without needing to be a separate predicate. The general syntax looks something like [Variables...]>>Goal. This sort of thing was previously available as library(lambda) and has been a feature of Logtalk for many years.

Upvotes: 1

lurker
lurker

Reputation: 58244

This is an ideal problem for maplist:

day_name(day(DayName), DayName).

dates_daylist(Dates, DayList) :-
    maplist(day_name, Dates, DayList).

Maplist applies day_name to each corresponding pair of elements in Dates and DayList.

Upvotes: 4

Related Questions