list出现次数最多 - python list更新



将列表元素的连续重复包装成子列表 (4)

因为[H|HS]是原始列表的尾部,所以您的第四个子句试图将[H|HS]附加到结果,这是不正确的。 你可以做得更简单 -

pack([H, H|HS], [[H|TFR]|TR]):-
    pack([H|HS], [TFR|TR]).

实质上,它说,当前两个条目在输入中相同时,第一个条目(即H )需要被前置到通过递归调用pack规则产生的输出列表的第一个条目。

请注意,第三个子句也可以简化,把Liste “破解”的Liste参数替换为子句头的“破解”版本,并对输出变量Ergebnis1做同样的处理。 最终版本应该是这样的:

pack([H, T|TS], [[H]|TR]):-
    H \= T,
    pack([T|TS], TR).

这是一个关于ideone的演示。

我需要一些帮助。 我通过数据库搜索, 发现有一个问题已经被问到这个例子,但答案并没有真正帮助我,所以我想发表我自己的问题。

任务是将连续重复的列表元素打包成子列表:

% ?- pack([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
% X = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]].

这是我得到的:

pack([], []).
pack([X], [[X]]).
pack(Liste, Ergebnis):-
   Liste = [H, T|TS],
   H \= T,
   pack([T|TS], Ergebnis1),
   append([[H]], Ergebnis1, Ergebnis).
pack([H, H|HS], Ergebnis):-
   pack([H|HS], Ergebnis1),
   append([H|HS], Ergebnis1, Ergebnis).

第一个案例工作得很好(案例H = T)。 第二个不是,我真的不知道为什么。 有人可以帮我解释一下我的解决方案的问题吗?

谢谢


我会以不同的方式解决问题,并将问题分解为两个更简单的任务。

我们首先需要能够将列表分成一个前缀,它包含列表头部的连续元素列表及其后缀 (其他所有内容):

partition( []      , []    , []     ) .
partition( [X]     , [X]   , []     ) .
partition( [X,Y|Z] , [X]   , [Y|Z]  ) :- X \= Y .
partition( [X,Y|Z] , [X|P] , S      ) :- X  = Y , partition([Y|Z],P,S) .

一旦我们有了,其余的很简单:

pack([],[]) .               % packing an empty list yields the empty list
pack([X|Xs],[P,Ps]) :-      % packing a non-empty list consists of
  partition([X|Xs],P,T) ,   % - partitioning it into its prefix and suffix, and
  pack(T,Ps)                % - packing the suffix
  .                         %

为避免追加,可以使用dcg :

pack(L, LP) :-                  % pack/2
    phrase(pack(L), LP).

pack([]) --> [].                % pack//1
pack([X]) --> [[X]].
pack([H, H1 | T]) -->
     {H \= H1},
     [[H]],
     pack([H1 | T]).
pack([H, H | T]) -->
    pack([H | T], [H]).

pack([H, H | T], P) -->         % pack//2
    pack([H | T], [H|P]).
pack([H, H1 | T], P) -->
    {H \= H1},
    [[H | P]],
    pack([H1 | T]).
pack([H, H], P) -->
    [[H,H|P]].

在这个问题的答案中给出的每个其他实现在逻辑上不纯的 。 它们不是单调的,因此在非基础条件下使用时很容易变得不合逻辑。

这里建议的实现是逻辑上纯的 。 它使用基于if_ / 3的元谓词splitlistIfAdj / 3 ,如@false在实例化答案中所提出的那样。

所以,让我们使用splitlistIfAdj/3dif/3 ,这是dif/2一个具体化变体:

?- splitlistIfAdj(dif,[a,a,a,a,b,c,c,a,a,d,e,e,e,e],Lists).
Lists = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]. % succeeds deterministically

因为我们在这里保持单调 ,即使我们使用非基础条件,我们也能得到有意义的答案:

?- splitlistIfAdj(dif,[A,B,C],Lists).
A = B,    B = C,    Lists = [[C, C, C]]    ;
A = B,    dif(B,C), Lists = [[B, B], [C]]  ;
dif(A,C), B = C,    Lists = [[A], [C, C]]  ;
dif(A,B), dif(B,C), Lists = [[A], [B], [C]].




prolog