views:

50

answers:

2

Hi. I have a problem where I have a list like this:

[[el1, el2, el3],
 [el4, el5, el6],
 [[el7, el8, el9], [el10, el11, el12], ..... , [elxx, elyy, elzz]],
[el, el, el]...]]

I want to pattern match the inner list of lists, the

[el7, el8, el9], [el10, el11, el12], ..... , [elxx, elyy, elzz]

How can this be done?

As of now I patternmatch the other elements with

my_method([[El1, El2, El3] | Rest]).

UPDATE

I want to pattern match if the next item of the list is a list of lists - I will be iterating over this list, removing item after item. There can be any number of lists of lists, and they can contain any number of items. They can also contain lists of lists. In fact, I will recursively call the same processing method whenever I come upon a list of lists.

All bottom level lists will have three elements, however these elements might be different:

[1, p, neg(5,6)] [5, neg(7,6), assumption]

A: 

You can use predicates similar to the following.

qualify([], []).
qualify([H|T], [HN|TN]) :- qualify_one(H, HN), qualify(T, TN).

qualify_one([H|_], N) :- qualify_one(H, N1), N is N1 + 1, !.
qualify_one(_, 0).

What qualify does is for each member of the list to find out on what level of the scale “not a list”, “simple list”, “list of lists”, … it is, based on the first item.

Example:

?- qualify([1,[2,3,3],[[4,5,6], [7,8,9]]], NS).
NS = [0, 1, 2].
svick
A: 

You said "I will be iterating over this list, removing item after item", so here's code that does just that, assuming an "item" is a three-element list of non-lists.

nested_member(X,X) :-
    X = [A,_,_],
    \+ is_list(A).
nested_member(X,[L|_]) :-
    nested_member(X,L).
nested_member(X,[_|L]) :-
    nested_member(X,L).

This can be used to backtrack over the "items":

?- nested_member(X,[[el1, el2, el3], [el4, el5, el6],
                    [[el7, el8, el9], [el10, el11, el12],[elxx, elyy, elzz]]]).
X = [el1, el2, el3] ;
X = [el4, el5, el6] ;
X = [el7, el8, el9] ;
X = [el10, el11, el12] ;
X = [elxx, elyy, elzz] ;
false.

I you want, you can even find out how deep in the list the items were found:

nested_member(X,L,D) :-
    nested_member(X,L,0,D).
nested_member(X,X,D,D) :-
    X = [A,_,_],
    \+ is_list(A).
nested_member(X,[L|_],D0,D) :-
    D1 is D0+1,
    nested_member(X,L,D1,D).
nested_member(X,[_|L],D0,D) :-
    nested_member(X,L,D0,D).
larsmans
@lars I don't have that much knowledge about Prolog... Could you explain in a bit more detail, like what does \+ is_list(A) mean? Why do you put X = [A, _, _]? The first X only matches the second X if they are equal, right?
Max Malmgren
`\+` is negation, so `A` may not be a list. `X=[A,_,_]` matches `X` with a three-element list, naming the first member of the list `A`. And yes, if two arguments have the same name, then they must be equal. In the intended use case, this means the first argument (a variable) gets set to the value of the second argument.
larsmans