在prolog中过滤列表

MRM*_*MKR 5 prolog

我正在尝试将代码从Haskell重写为Prolog.

count :: Eq a => a -> [a] -> Int
count x = length . filter (x==)

f :: [Integer] -> [Integer]
f [] = []
f list = filter (\x -> count x list == 1) list 
Run Code Online (Sandbox Code Playgroud)

此代码返回列表包含仅在列表中出现一次的元素.所以如果我有列表[1,1,2,2,3,4,4,5]这个函数返回[3,5] 我试图在Prolog中找到过滤器构造,但似乎没有这样的事情.如何在Prolog中创建类似的功能?

mat*_*mat 6

对于现有的答案,我想添加一个非常通用的答案,你可以在多个方向上使用它.

积木: list_element_number/3

我从以下谓词开始,定义以下关系:

  • 一份清单 Ls0
  • 一个元素 E
  • N的出现ELs0

这里是:

list_element_number(Ls0, E, N) :-
        tfilter(=(E), Ls0, Ls),
        length(Ls, N).

此解决方案使用tfilter/3from library(reif).谓词包含count您发布的函数.这个谓词相对于函数的主要好处是谓词不仅可以用于那些甚至Haskell都可以轻松完成的情况,例如:

?- list_element_number([a,b,c], a, N).
N = 1.

不,我们也可以在其他方向使用它,例如:

?- list_element_number([a,b,c], X, 1).
X = a ;
X = b ;
X = c ;
false.

甚至:

?- list_element_number([a,b,E], X, 2).
E = X, X = a ;
E = X, X = b ;
false.

甚至:

?- list_element_number([A,B,C], X, 3).
A = B, B = C, C = X ;
false.

甚至在最常见的情况下,所有参数都是新变量:

?- list_element_number(Ls, E, N).
Ls = [],
N = 0 ;
Ls = [E],
N = 1 ;
Ls = [E, E],
N = 2 ;
Ls = [E, E, E],
N = 3 .

我们可以公平地列举所有这样的答案:

?- length(Ls, _), list_element_number(Ls, E, N).
Ls = [],
N = 0 ;
Ls = [E],
N = 1 ;
Ls = [_160],
N = 0,
dif(E, _160) ;
Ls = [E, E],
N = 2 .

主谓词: list_singletons/2

使用这个构建块,我们可以定义list_singletons/2如下:

list_singletons(Ls, Singles) :-
        tfilter(count_one(Ls), Ls, Singles).

count_one(Ls, E, T) :-
        list_element_number(Ls, E, Num),
        cond_t(Num=1, true, T).

这使用cond_t/3和(再次)tfilter/3来自library(reif).

示例查询

以下是一些示例查询.首先,您发布的测试用例:

?- list_singletons([1,1,2,2,3,4,4,5], Singles).
Singles = [3, 5].

它按预期工作.

现在涉及变量的案例:

?- list_singletons([A,B], Singles).
A = B,
Singles = [] ;
Singles = [A, B],
dif(A, B).

在回溯时,会生成所有可能性:要么 A = B保持,要么在这种情况下,没有任何元素只出现一次.或者 A不同的  B,在这种情况下,两个AB出现一次.

作为上述查询的特例,我们可以发布:

?- list_singletons([A,A], Singles).
Singles = [].

作为概括,我们可以发布:

?- length(Ls, _), list_singletons(Ls, Singles).
Ls = Singles, Singles = [] ;
Ls = Singles, Singles = [_7216] ;
Ls = [_7216, _7216],
Singles = [] ;
Ls = Singles, Singles = [_7828, _7834],
dif(_7828, _7834) ;
Ls = [_7216, _7216, _7216],
Singles = [] ;
Ls = [_7910, _7910, _7922],
Singles = [_7922],
dif(_7910, _7922) .

享受这种关系的普遍性,通过获得.