替换嵌套列表中的一个或多个元素

时间:2017-01-28 11:11:33

标签: list replace prolog

我正在努力实现这一目标:

鉴于OldList,如果该项目符合目标(oldNew),则替换任何项目;如果没有,请不要更换该项目。

返回NewList,其中包含与OldList具有相同结构(即相同嵌套)的已替换项目。

我为特殊情况OldList = [a, b, c]开始工作(参见我的代码),但我想写一个谓词,它可以概括列表长度和嵌套列表,例如:也适用于OldList = [a, [b, c, [d, e]]]

提前致谢! / JC

oldNew(fruit, banana).
oldNew(car, ferrari).

replace(OldList, NewList):-
    [X1, X2, X3] = OldList,
    (oldNew(X1, Y1); Y1 = X1),
    (oldNew(X2, Y2); Y2 = X2),
    (oldNew(X3, Y3); Y3 = X3),
    (oldNew(X1, Y1); oldNew(X2, Y2), oldNew(X3, Y3)),
    NewList = [Y1, Y2, Y3].

EDIT1:

使用任意列表长度;但我仍然不知道如何处理嵌套列表。

replace2(OldList, NewList):-
    [H | T] = OldList,
    oldNew(H, NewHead),
    NewList = [NewHead | T].
replace2(OldList, NewList):-
    [H | T] = OldList,
    replace2(T, NewTail),
    NewList = [H | NewTail].

1 个答案:

答案 0 :(得分:2)

通常,模式匹配在头部是明确的。代码更清晰:

replace2([], []).
replace2([H|T], [Ht|Tt]) :-
  (  oldNew(H, Ht)
  -> true
  ;  is_list(H)
  -> replace2(H, Ht)
  ;  H = Ht
  ),
  replace2(T, Tt).

在SWI-Prolog库applyyall允许稍微缩短的代码:

replace2(L, T) :- maplist([H,Ht]>>
  (  oldNew(H, Ht)
  -> true
  ;  is_list(H)
  -> replace2(H, Ht)
  ;  H = Ht
  ), L, T).

您可以看到括号内的分离已从前一个定义中复制并粘贴。它是一个lambda应用程序......

?- replace2([aa, car, apple, fruit, any, [aa, car, apple, banana, any]], T).
T = [aa, ferrari, apple, banana, any, [aa, ferrari, apple|...]].