Max
Max

Reputation: 4405

Pattern matching list of lists

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]

Upvotes: 1

Views: 2037

Answers (2)

Fred Foo
Fred Foo

Reputation: 363547

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).

Upvotes: 1

svick
svick

Reputation: 244767

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].

Upvotes: 1

Related Questions