根据第 n 个元素删除列表中的列表

Removing list within lists based on nth element

我有一个列表列表,例如:

[[1, 2, 3, 2], [1, 3, 4, 3], [1, 4, 5, 4], [2, 3, 5, 6], [1, 5, 6, 5], 
[2, 4, 6, 8], [1, 6, 7, 6], [2, 5, 7, 10], [3, 4, 7, 12], [2, 6, 8, 12]]

我想获取 的最后一个元素并检查它是否与任何其他列表的第四个元素相同。如果相同则保留列表,但如果唯一则删除列表。所以在上面的例子中我会留下:

[[3, 4, 7, 12], [2, 6, 8, 12]]

基本上我想删除最后一个元素唯一的所有列表。 我写了一个谓词来获取第 n 个元素:

my_membership(X, [X|_]).                           
my_membership(X, [_|Tail]) :-  
  my_membership(X, Tail).       

其中:

my_membership([_,_,_,Fourth],[[3, 4, 7, 12], [2, 6, 8, 12]]).

给出:

Fourth = 12 
Fourth = 12 

从构建两个基本谓词开始:

last([X], X).
last([_|T], X) :- last(T, X).

forth([_,_,_,F|_], F).

第一个谓词提取列表的最后一个元素;第二个谓词提取列表的第四个元素。

现在您可以创建一个谓词来计算一个元素 X 在列表列表的任何列表中出现的第四位。下面,H in [H|T] 是一个列表:

matching_forth([], _, 0).
matching_forth([H|T], X, R) :- forth(H, X), matching_forth(T, X, RR), R is RR + 1.
matching_forth([_|T], X, R) :- matching_forth(T, X, R).

有了这些谓词,您就可以构建一个谓词来检查您的条件。它将有三个子句 - 列表为空的情况,当头列表在另一个列表中有匹配的第四个元素时,以及没有的情况:

my_membership([], [], _).
my_membership([H|T], [H|R], A) :-
   last(H, X), matching_forth(A, X, C), C > 1, my_membership(T, R, A).
my_membership([_|T], R, A) :- my_membership(T, R, A).

第一个和最后一个子句是不言自明的。中间子句从头列表中提取最后一个元素,计算它与原始列表列表中的第四个元素匹配的次数(A代表"all"),并将H添加到匹配时的结果。添加是通过与结果列表的头部统一来实现的。

最后,您需要一个 my_membership/2 谓词来启动沿原始列表列表传递的递归链:

my_membership(L, R) :-  my_membership(L, R, L).

Demo.

这是对潜在解决方案的不同看法。它使用一个累加器来收集我们已经看到的成员并沿途进行检查。结果保存那些已经被看到或当前在尾部的。它需要使用内置的 memberchk/2.

my_membership(L, R) :-
    my_membership(L, [], R).

my_membership([], _, []).
my_membership([X|T], Acc, R) :-
    X = [_,_,_,D],
    (   memberchk([_,_,_,D], Acc)
    ->  R = [X|T1],
        Acc1 = Acc
    ;   memberchk([_,_,_,D], T)
    ->  R = [X|T1],
        Acc1 = [X|Acc]
    ;   R = T1,
        Acc1 = Acc
    ),
    my_membership(T, Acc1, T1).

| ?- my_membership([[1, 2, 3, 2], [1, 3, 4, 3], [1, 4, 5, 4], [2, 3, 5, 6], [1, 5, 6, 5],
[2, 4, 6, 8], [1, 6, 7, 6], [2, 5, 7, 10], [3, 4, 7, 12], [2, 6, 8, 12]], L).

L = [[2,3,5,6],[1,6,7,6],[3,4,7,12],[2,6,8,12]]

yes