user3115959
user3115959

Reputation: 11

Working with lists of lists in Prolog

New to , trying to get my head around dealing with lists of lists recursively.

Say I have a list:

prices([20, 20, 40]).

And another list (of lists):

items([ [12, 14, 23],[8, 16, 22],[18, 12, 14] ]).

I want to append an element from prices to each list in items:

items([ [12, 14, 23, 20],[8, 16, 22, 20],[18, 12, 14, 40] ]).

I'm having trouble with working through both a single list and a list of lists at the same time.

Any pointers would be appreciated.

Thanks!

Upvotes: 1

Views: 232

Answers (3)

lurker
lurker

Reputation: 58224

It's not too difficult if you sort it out in its appropriate pieces. In prolog, a list is a list until you need to do something with an element.

item_prices(ItemPrices) :-
    prices(Prices),
    items(ItemLists),
    item_prices(ItemLists, Prices, [], ItemPrices), !.
item_prices([ItemList|ItemLists], [Price|Prices], SoFar, ItemPrices) :-
    append(ItemList, [Price], ItemPrice),  % Assumes the items are lists, price is not
    item_prices(ItemLists, Prices, [ItemPrice|SoFar], ItemPrices).
item_prices(_, _, ItemPrices, ItemPrices).

Then you'd just call:

item_prices(ItemPrices).

To give:

ItemPrices = [[18,12,14,40],[8,16,22,20],[12,14,23,20]]

Upvotes: 4

CapelliC
CapelliC

Reputation: 60004

this is a variation on mbratch answer

item_prices(ItemPrices) :-
    prices(Prices),
    items(ItemLists),
    item_prices(ItemLists, Prices, ItemPrices), !.
item_prices([ItemList|ItemLists], [Price|Prices], [ItemPrice|ItemPrices]) :-
    append(ItemList, [Price], ItemPrice),  % Assumes the items are lists, price is not
    item_prices(ItemLists, Prices, ItemPrices).
item_prices([], [], []).

without an accumulator, we avoid to reverse the order.

Here is a solution, using maplist/3, handy when you must perform the same operation among matched lists elements:

items_updated(Us) :-
    items(Is),
    prices(Ps),
    maplist(append_, Is, Ps, Us).
append_(Is, P, R) :- append(Is, [P], R).

Upvotes: 2

Will Ness
Will Ness

Reputation: 71070

any time you have difficulty in dealing with too much stuff at the same time, see if you can separate your concerns and deal with each separately, through an auxiliary predicate.

For instance here you could define add_to_end( Element, List, Newlist) and use it in your main predicate.

add_to_end( E, [], R):- R = ... .
add_to_end( E, [A|B], R):- R=[A|X], add_to_end( E, B, ...).

When you've mastered the basics of the language, do see what's there in the library; chances are there's already a predicate that lets you append two lists, which you could use somehow instead of writing your own specialized version of it. After all, add_to_end( E, L, R) == append_two_lists(L, [E], ...).

Upvotes: 2

Related Questions