【问题标题】:Removing unique elements from list in prolog从序言中的列表中删除唯一元素
【发布时间】:2017-06-04 16:11:47
【问题描述】:

我正在尝试从 Prolog 的列表中删除唯一元素。

输出应该类似于:

?- rem_Uniq([3,3,1,7,a,c,c],D).
D = [3, c].

这是我当前的代码。

rem_Uniq(L1,L2).
rem_Uniq([L1|RL1], [L1|D]) :-
    member(L1,RL1),
    rem_Uniq(RL1,D).
rem_Uniq([L1|RL1], D) :-
    remove(L1[L1|RL1], O),
    rem_Uniq(O, D).

目前,无论我做什么,它都会返回 true(无论我输入是否包含唯一变量的列表)。

有人对我做错了什么有任何想法或建议吗?

【问题讨论】:

    标签: prolog


    【解决方案1】:

    D 是列表中仅出现一次的元素集合。

    在Prolog中“一个在列表中只出现一次的元素”可以翻译为

    select(X, L, L_X),
    \+member(X, L_X)
    

    在 Prolog 中存在收集具有特定属性 setof/3bagof/3 的元素的谓词。

    bagof 收集所有元素,setof 只保留一个元素。 所以你可以写

    rem_uniq(In, Out) :-
        setof(X, In_X^(select(X, In, In_X),\+member(X, In_X)), Out).
    

    [编辑]

    现在我们只需要列表中重复的元素。如果我删除列表中的这些元素之一,它将在列表中保留具有相同值的其他元素,以便它可以在 Prolog 中通过

    select(X, In, In_X),
    member(X, In_X)
    

    (我们说 select(X, In, In_X),member(X, In_X) 成功)。 现在可以写代码了

    rem_uniq(In, Out) :-
        setof(X, In_X^(select(X, In, In_X),member(X, In_X)), Out).
    

    例如

    ?- rem_uniq([3,3,1,7,a,c,c],D).
    D = [3,c].
    

    请注意,如果没有可用的元素,setof 将失败

     ?- rem_uniq([3,1,7,a,c],D).
    false.
    

    【讨论】:

    • 感谢您的回答 joel76,但是它只保留独特的元素......而不是重复的元素。我将如何改变它?只是一个小指针,不一定是如何做的代码......我想尝试解决它。对不起,顺便说一句,我只是不明白序言
    • 如何在 Prolog 中翻译“一个元素在列表中重复”?在我的翻译代码中没有太多需要做的改变。 (选择删除列表的元素 X)。
    • 很遗憾我无法解决这个问题。无论如何,我想感谢您的帮助,因为我理解了这个问题,我开始研究 prolog 中的所有谓词,并且第一次真正开始了解它们的实际作用。我可能不会为我的家庭作业提交正确的答案,但是这是我根据您的答案了解 prolog 实际工作原理的最接近的方法,所以我称之为胜利......有点?不管怎么说,还是要谢谢你 :)。也许更多的练习会帮助我得到它。
    • @TheLeftRight 我对我的答案进行了编辑以解决您的问题
    • 现在我看到了,我不明白我怎么不能解决这个问题......现在看起来很简单......非常感谢您的帮助。
    【解决方案2】:

    嗯,你的第一个问题是你的第一个子句:

    rem_Uniq(L1,L2).
    

    这字面意思是“任何两件事都是相互的 rem_Uniq”。这就是在没有统一的情况下总是变得真实的原因。你可能是这个意思:

    rem_Uniq([], []).
    

    您的第二个问题是这不是有效的语法:

     remove(L1[L1|RL1], O),
    

    具体来说,L1[L1|RL1],我不清楚你的意思。我想你的意思是delete(L1, [L1|RL1], O)

    现在,从算法上讲,我认为您有点困惑。在第 #2 条中,您在结果中将 L1 添加到 D,也就是说,在知道 L1 存在于 RL1 中并使用递归调用将其从 D 中删除之后。但是在第 # 条中3,您只需将其从 [L1|RL1] 中删除以生成 O,然后从中删除唯一性。

    递归谓词的每个子句都应该代表一个您必须担心的情况。我真的不明白这些条款是什么意思。第一个应该是,以防列表为空。第二个应该是列表不为空的情况。您似乎在这里尝试做的是,在列表不为空且包含 head 元素的情况下,以及在列表不为空且不包含 head 元素的情况下,但有或没有那个元素对你的图书馆程序来说是(或应该是)毫无意义的。换句话说,delete/3 在一个非空递归情况下应该完全足以解决这个问题:

    rem_uniq([], []).
    rem_uniq([X|Xs], [X|UniqueXs]) :- 
      delete(X, Xs, XsWithoutX),
      rem_uniq(XsWithoutX, UniqueXs).
    

    所以,我认为您对何时以及为什么应该有多个子句有些困惑,而且我认为您选择的变量名可能会让您的生活更加艰难。但这只是我的猜测。

    希望这会有所帮助!

    【讨论】:

    • 谢谢丹尼尔。我目前正在工作,但我回家后会玩这个。非常感谢您的深入回答和解释
    • 嗨丹尼尔,我一直在玩这个代码,现在无论列表中是否有重复,它都会返回 false?我做错了吗?
    猜你喜欢
    • 2015-01-08
    • 1970-01-01
    • 2013-06-14
    • 2017-10-09
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 2017-03-05
    相关资源
    最近更新 更多