Prolog-只从列表中获取相同的元素

时间:2015-12-05 08:42:04

标签: list prolog

我是Prolog编程的初学者。我有这个程序从列表中删除相同的元素?但我只想从列表中获得相同的元素。

带有预期答案的示例查询:

?- set([1,2,3,4,2,3], Xs).
Xs = [2,3].

Prolog代码:

ismember(X, SET) :-
   member(X, SET).

set([], []).
set([H|T], [H|Out]) :-
    not(ismember(H,T)),
    set(T, Out).
set([H|T], Out) :-
    ismember(H, T),
    set(T, Out).

谢谢!

2 个答案:

答案 0 :(得分:3)

以下内容源自this answer相关问题“Remove unique elements only”。

tpartition/4同时使用 if_/3(=)/3,我们定义remove_uniq/2,如下所示:

remove_uniq([], []).
remove_uniq([E|Es], Xs0) :-
   tpartition(=(E), Es, Ts, Fs),
   if_(Ts = [],
       Xs0 = Xs,
       Xs0 = [E|Xs]),
   remove_uniq(Fs, Xs).

示例查询:

:- remove_uniq([1,2,3,4,2,3], [2,3]).
%                 ^ ^          ^ ^
%                 |-+--------- take leftmost occurrence
%                 v v          v v 
:- remove_uniq([1,2,3,4,3,2], [2,3]).
%                 ^ ^          ^ ^
%                 |-+--------- preserve the original order
%                 v v              v v
:- remove_uniq([5,3,2,1,2,3,2,3], [3,2]).

答案 1 :(得分:2)

快速而肮脏

'slow quick and dirty'(S0, S) :-
    setof(C, R^(select(C,S0,R),member(C,R)), S).

'better quick and dirty'(S0, S) :-
    setof(C, R^(select(C,S0,R),memberchk(C,R)), S).

'still better quick and dirty'(S0, S) :-
    setof(H, Done^H^R^(append(Done,[H|R],S0),memberchk(H,R)), S).

test(N) :-
    findall(R, (between(1,N,_), random_between(10,100,R)), S),
    time('slow quick and dirty'(S, Sa)),
    time('better quick and dirty'(S, Sb)),
    time('still better quick and dirty'(S, Sc)),
    Sa = Sb, Sb = Sc,
    time(remove_uniq(S, Sd)),
    maplist(length, [Sa, Sb, Sc, Sd], Ls),
    writeln(Ls).

25 ?- so:test(100).
% 10,225 inferences, 0.003 CPU in 0.003 seconds (100% CPU, 3506071 Lips)
% 282 inferences, 0.001 CPU in 0.001 seconds (99% CPU, 226231 Lips)
% 254 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 347891 Lips)
% 22,697 inferences, 0.018 CPU in 0.028 seconds (65% CPU, 1272020 Lips)
[28,28,28,28]
true.

26 ?- so:test(1000).
% 1,011,929 inferences, 0.275 CPU in 0.276 seconds (100% CPU, 3674049 Lips)
% 3,015 inferences, 0.013 CPU in 0.013 seconds (98% CPU, 239535 Lips)
% 2,924 inferences, 0.013 CPU in 0.016 seconds (82% CPU, 216598 Lips)
% 351,724 inferences, 0.262 CPU in 0.272 seconds (96% CPU, 1343870 Lips)
[91,91,91,91]
true.

是否会生成并测试'图案。

表现如何?

SELECT
  razao_social,
  nome_fantasia,
  id,
  endereco,
  numero,
  cnpj,
  complemento,
  bairro,
  cidade,
  estado,
  tel1,
  tel2,
  email
FROM
  tbl_fornecedors
LIMIT 4 OFFSET 4
WHERE
  nome_fantasia LIKE '%example%'
ORDER BY nome_fantasia ASC;

出于好奇,我已经包含了remove_uniq / 2,但是,鉴于语义不同,我认为它不具有严格的可比性。

使用member / 2,我们有二次复杂度。 memberchk的运行时效率(在C语言中实现为builtin)只是挤掉了滤波器延迟:效率变得几乎是线性的。

append / 3而不是select / 3允许进一步的小改进。