【问题标题】:Remove both the value and all duplicates of that value in a list in prolog在 prolog 的列表中删除该值和该值的所有重复项
【发布时间】:2015-10-21 12:44:54
【问题描述】:

我在从 prolog 的列表中删除值时遇到了一些问题。 我有一个颜色列表,我想向其中添加一个颜色列表,并保留所有没有重复的值并删除其余的值。

[green, red, blue, purple, yellow, brown, orange, black, purple]

所以紫色在这个列表中出现了两次,我想删除它们。 这是我要返回的列表。

[green, red, blue, yellow, brown, orange, black]

我目前有这个可以删除所有重复项,但我无法将两个紫色都删除。

mymember(X,[H|_]) :- X==H,!.
mymember(X,[_|T]) :- mymember(X,T).

not(A) :- \+ call(A).

set([],[]).
set([Head|Tail],[Head|Out]) :-
    not(mymember(Head,Tail)),
    set(Tail, Out).
set([Head|Tail],Out) :-
    mymember(Head,Tail),
    set(Tail, Out).

这是我现在得到的结果:

[green, red, blue, yellow, brown, orange, black, purple]

【问题讨论】:

    标签: list prolog prolog-dif


    【解决方案1】:

    简单的方法...单线:

    singletons(Xs,Zs) :-
      findall( X , ( append(P,[X|S],Xs), \+member(X,P), \+member(X,S) ) , Zs )
      .
    

    【讨论】:

    • @repeat。请参阅我更简单的答案。
    【解决方案2】:

    tfilter/3list_uniqmember_t/3结合使用,留在 pure

    list_uniqs(Es, Us) :-
       tfilter(list_uniqmember_t(Es), Es, Us).
    

    OP给出的示例查询具有预期结果:

    ?- list_uniqs([green,red,blue,purple,yellow,brown,orange,black,purple], Xs).
    Xs = [green,red,blue,yellow,brown,orange,black]. % succeeds deterministically
    

    对于更一般的查询,我们是否也能得到合乎逻辑的合理答案?

    ?- list_uniqs([A,B,A], [])。 A=B ;错误的。 ?- list_uniqs([A,B,A], [_])。 差异(A,B)。 ?- list_uniqs([A,B,A], [_,_])。 错误的。 ?- list_uniqs([A,B,A], Xs)。 Xs = [] , A=B ; Xs = [B],差异(A,B)。

    是的!更一般的一点怎么样?

    ?- list_uniqs([A,B,C],Xs)。 Xs = [] , A=B , B=C ; Xs = [C] , A=B , 差异 (B,C) ; Xs = [B] , A=C , 差异 (B,C) ; Xs = [A] , 差异 (A,C), B=C ; Xs = [A,B,C], dif(A,B), dif(A,C), dif(B,C)。

    有效!

    【讨论】:

      【解决方案3】:

      我认为你在正确的轨道上。这是一种使用 -> 的方法;构造并利用 delete/3 谓词,它会删除所有重复项:

      remdup([], _, []).
      remdup([H|T], X, R) :-
          (   H == X
          ->  (   member(X, T)
              ->  delete(T, X, R)     % only delete if it's in the list more than once
              ;   R = [H|R1],
                  remdup(T, X, R1)
              )
          ;   R = [H|R1],
              remdup(T, X, R1)
          ).
      

      另一种解决方案,使用select/3 以及delete/3

      remdup(L, X, R) :-
          (select(X, L, L1), select(X, L1, L2))
      ->  delete(L2, X, R)
      ;   L = R.
      

      select/3 从列表中提取元素的一个实例。如果找不到元素,则失败。因此,在上面,如果我们能够找到至少两个实例,我们将删除所有实例。


      执行整个列表的解决方案(减去指定要删除的单个项目的中间参数):
      remdup([], []).
      remdup([H|T], R) :-
          (   select(H, T, T1)
          ->  delete(T1, H, R1),
              remdup(R1, R)
          ;   R = [H|R1],
              remdup(T, R1)
          ).
      

      【讨论】:

        【解决方案4】:

        我通过这样做修复了它:

        my_delete(Res, [], Res).
        my_delete(Colorslist, [Head|Tail], R) :-  
            my_delete_worker(Colorslist, Head, Result), 
            my_delete(Result, Tail, R).
        
        my_delete_worker([], _, []).
        my_delete_worker([X|T], X, R) :-
            my_delete_worker(T, X, R).
        my_delete_worker([H|T], X, [H|R]) :-
            X \= H,
            my_delete_worker(T, X, R).
        

        我忘记将第一种颜色的结果放入第二种颜色的颜色列表中。当它到达基本情况时,我将我的颜色列表与结果统一起来。 感谢潜伏者的帮助!

        【讨论】:

        • 您的my_delete_worker/3 谓词将删除一个元素,即使它是列表中唯一的元素。例如,my_delete_worker([a,b,c], b, R). 产生 R = [a,c]。我以为这就是你想要避免的?
        【解决方案5】:

        更简单(而且不纯:-)

        singletons(Xs, Zs) :- findall(X, (select(X,Xs,Ys), \+memberchk(X,Ys)), Zs).
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多