1

我想从列表中删除元素,但如果我这样做:

deletelist([3,1,2,3,4], [3], [3,1,2,4]) 

如何只删除一个 3 而没有得到这个答案:

deletelist([3,1,2,3,4], [3], [1,2,4])

谢谢!

4

2 回答 2

2

select /3 它是一个有用的内置函数,经常用于generate and test,您可以使用它来删除元素:

?- select(3,[3,1,2,3,4],L).
L = [1, 2, 3, 4] ;
L = [3, 1, 2, 4] ;
false.

每次调用都会删除一个匹配项,然后您可以控制所需的行为

编辑

从第二个列表中删除所有元素:

deletelist(L, [], L).
deletelist(With, [D|Ds], Without) :-
    select(D, With, WithoutD),
    deletelist(WithoutD, Ds, Without).

请注意,如果在列表中找不到任何要删除的元素,这将失败。为避免这种情况,请应用“if .. then .. else ..”

deletelist(L, [], L).
deletelist(With, [D|Ds], Without) :-
    (  select(D, With, WithoutD)
    -> deletelist(WithoutD, Ds, Without)
    ;  deletelist(With, Ds, Without)
    ).

现在 deletelist/3 不会枚举所有可能的删除。它承诺第一个找到的。要恢复初始行为,即回溯所有不同的删除,需要一个效率较低的过程:

deletelist(L, [], L).
deletelist(With, [D|Ds], Without) :-
    select(D, With, WithoutD),
    deletelist(WithoutD, Ds, Without).
deletelist(With, [D|Ds], Without) :-
    \+ select(D, With, _),
    deletelist(With, Ds, Without).
于 2013-01-22T11:55:03.857 回答
1

如果您只想获取列表中的唯一值 - 使用函数list_to_set/2

list_to_set([3,1,2,3,4],X)X = [3, 1, 2, 4].

编辑:

所以gnu prolog没有内置的 predicate list_to_set。你必须自己写。为此,您必须定义集合概念。是什么set of list?Set 应具有以下属性:

  • 集合大小必须小于或等于列表大小。
  • Set 的所有成员都必须是 List 的成员。
  • List 的所有成员都必须是 Set 的成员。
  • Set 不得包含重复的值。

基于这些假设,您可以set_from_list像这样编写谓词:

elem_unique(Elem, List) :-
  delete(List, Elem, ListWithoutElem),
  length(List, OrgLength),
  length(ListWithoutElem, DelLength),
  DelLength + 1 =:= OrgLength.

nth_elem_isUnique(N, List) :-
  nth1(N, List, Elem),
  elem_unique(Elem, List).

nth_elemOfList1_isMemberOfList2(N, List1, List2) :-
  nth1(N, List1, Elem),
  member(Elem, List2).

elements_from_nth_areUnique(N, List) :-
  (length(List, Len),
  N > Len)    %stoping condition for recursion
  ;
  (nth_elem_isUnique(N, List),
  M is N + 1,
  elements_from_nth_areUnique(M, List)   %recursion part
  ).

listIsUnique(List) :-
  elements_from_nth_areUnique(1, List).

elements_from_nth_inList1_areMembersOfList2(N, List1, List2) :-
  (length(List1, Len),
  N > Len)    %stoping condition for recursion
  ;
  (nth_elemOfList1_isMemberOfList2(N, List1, List2),
  M is N + 1,
  elements_from_nth_inList1_areMembersOfList2(M, List1, List2)  %recursion part
  ).

list2containsList1(List1, List2) :-
  elements_from_nth_inList1_areMembersOfList2(1, List1, List2).

set_from_list(Set, List) :-
  length(Set, LenSet),
  length(List, LenList),
  LenSet =< LenList,
  list2containsList1(List, Set),
  list2containsList1(Set, List),
  listIsUnique(Set),
  !.

所以打电话后set_from_list(Set, [3,1,2,3,4])你会得到Set = [3,1,2,4]

于 2013-01-22T11:01:26.080 回答