从Prolog中的行列表中提取列

时间:2017-03-14 17:22:48

标签: prolog

我试图从行列表(X)中提取索引(K)的某个列(COLUMN)。

这是我到目前为止编写的代码:

extract(K,X,COLUMN):-
    constructColumn(K,1,X,COLUMN).


constructColumn(K,B,X,COLUMN):-
    nth1(B,X,LINE),
    nth1(K,LINE,ELEMENTCOLUMN),
    incr(B,B1),
    constructColumn(K,B1,X,ELEMENTCOLUMN|COLUMN);
    !.

incr(X, X1) :- X1 is X+1.

当我追踪它的运作方式时,我发现我正在构建的新COLUMN列表不会在结尾处作为输出提供,它只输出true。有没有办法以类似的方式向谓词添加元素?

3 个答案:

答案 0 :(得分:2)

maplist/3谓词在这里也运作良好。 maplist将谓词应用于一组列表参数,从而产生其他列表参数,其中该谓词用于处理一个参数。

因此,您可以将extract/3写为:

extract(ColNumber, Matrix, Column) :-
    maplist(nth0(ColNumber), Matrix, Column).

你已经完成了。 :)

| ?- extract(2, [[a,b,c,d],[e,f,g,h],[i,j,k,l]], R).

R = [c,g,k]

yes
| ?-

答案 1 :(得分:0)

由于你有很多次迭代,你可以使用findall/3谓词跳过大部分的写作:

extract(K,X,COLUMN):- findall(Elem , (member(X1,X), nth0(K,X1,Elem)) , COLUMN).

上面做的是每个X1行(X行的成员)采用Kth元素(使用nth0/3谓词)并将其存储到COLUMN列表。

您可以在此处阅读findall/3www.swi-prolog.org/pldoc/man?predicate=findall/3

示例:

?- extract(1,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [2, 22, 222].

?- extract(0,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [1, 11, 111].

?- extract(2,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [3, 33, 333].

?- extract(3,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [4, 44, 444].

?- extract(5,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [].

答案 2 :(得分:0)

只是为了显示使代码正常工作所需的修改:

extract(K,X,COLUMN):-
    constructColumn(K,1,X,COLUMN).

constructColumn(K,B,X,[ELEMENTCOLUMN|COLUMN]):-
    nth1(B,X,LINE),
    nth1(K,LINE,ELEMENTCOLUMN),
    succ(B,B1),
    !,
    constructColumn(K,B1,X,COLUMN).
constructColumn(_K,_B,_X,[]).

让我们解释一下:我们使用nth1(B,X,LINE)来访问每一行,当它失败时,我们就完成了。第一个改进可能是通过索引删除对行的访问:只需让列表(列表)控制递归:

extract(_,[],[]).
extract(K,[LINE|LINES],[ELEMENTCOLUMN|COLUMN]):-
    nth1(K,LINE,ELEMENTCOLUMN),
    extract(K,LINES,COLUMN).

好多了,不是吗?