【问题标题】:How to delete from a list the 1st, 2nd ,4th and 8th elements in Prolog如何从列表中删除 Prolog 中的第 1、第 2、第 4 和第 8 个元素
【发布时间】:2015-11-05 09:15:12
【问题描述】:

我想从列表中删除第一个、第二个、第四个和第 8 个元素。 我能怎么做? 我试过这个:

 del([],[]).
 del([H1,H2,H3,H4|T],[H3|T]).

它可以工作,但我怎样才能递归地做到这一点,而不是写 8 个元素来删除我想要的位置?

【问题讨论】:

  • 我认为答案取决于您希望如何概括问题。 Jay 的回答假设您想要一个完全通用的解决方案,在该解决方案中,您将获得要删除的元素的索引列表。对于一组固定的索引,Paulo 的解决方案更为直接。如果n 是2 的幂,则第三个选项是您想要删除元素n。第一个和第三个选项将使用递归,但第二个不需要它。那么你想以什么方式定义我想要的职位
  • 这四个是您要删除的项目的唯一索引吗?

标签: list prolog


【解决方案1】:

统一是你的朋友:

delete_one_two_four_eight_elements(
    [_, _, Third, _, Five, Six, Seven, _| Rest],
    [Third, Five, Six, Seven| Rest]
).

【讨论】:

  • 如果我理解正确,原始发帖人想要一个递归解决方案,而不是枚举每个第 n 个元素(大概是这样可以使用不同的索引集),但我可能是错的......
【解决方案2】:

如果将索引作为递增的值列表给出,则一般解决方案也可以使用 DCG 完成:

del([C|Ns], C, Xs) --> [_], { C1 #= C + 1 }, del(Ns, C1, Xs).
del([N|Ns], C, [X|Xs]) --> [X], { N #\= C, C1 #= C + 1 }, del([N|Ns], C1, Xs).
del([], _, Xs) --> rest(Xs).
del(_, _, []) --> [].     % ***

rest([]) --> [].
rest([X|T]) --> [X], rest(T).

delete_indices(Indices, List, Result) :-
    phrase(del(Indices, 1, Result), List).

使用上面包含的子句***,超出列表长度的索引将被忽略:

| ?- delete_indices([1,3,5,12], [a,b,c,d,e,f,g], L).

L = [b,d,f,g] ? ;

no
| ?-

如果您省略*** 子句,则索引超出列表长度的查询将失败,因此上述查询将失败(因为没有第 12 个元素),但仅具有现有索引的列表将起作用:

| ?- delete_indices([1,3,5], [a,b,c,d,e,f,g], L).

L = [b,d,f,g] ? ;

no
| ?-

请注意,可以使用if_//3 实现确定性解决方案。

【讨论】:

    【解决方案3】:

    那么...编写一个谓词删除第 n 个元素,然后编写一个包含索引列表并删除所有这些元素的谓词怎么样?

    删除第n个很简单:

    del([_|T],T,1).
    del([Head|Tail],B,N) :-
        K is N-1,
        del(Tail,C,K),
        B = [Head|C].
    

    由于我们知道 N 不是 1(否则会使用第一个子句),我们保留第一个子句(请参阅 B=[Head|C],我们没有将 Head 扔掉!)并递归调用 @ 987654324@ 确定C 删除第n 个。

    现在,对于 listdel,它需要一个索引列表:

    listdelaux(A,A,[],_).
    listdelaux(A,B,Indices,Level) :-
        Indices = [N|IndicesTail],
        K is N-Level,
        del(A,X,K),
        L is Level + 1,
        listdelaux(X,B,IndicesTail,L).
    
    listdel(A,B,Indices) :- listdelaux(A,B,Indices,0).
    

    listdelaux 谓词有四个参数:原始列表、新列表、索引列表和级别,在第一次调用中应该为零。 它将删除第一个索引;然后再次为下一个索引调用自身,但是在新调用中它应该从要删除的新索引中减去已删除的索引数:

    [a,b,c,d,e,f] 中删除[2,4]

    [a,b,c,d,e,f] --> del(.,.,2) --> [a,c,d,e,f]
    
    [a,c,d,e,f] --> del(.,.,3) --> [a,c,e,f]
    

    看到我们必须在第二次调用中从 4 中减去 1。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      相关资源
      最近更新 更多