序言误解。将列表拆分为两个列表,其中偶数位置和奇数位置。我的错误在哪里?

prolog misunderstanding. Split list into two list with even and odd positions. where is my mistake?

我正在尝试将一个列表拆分为另外两个列表。列出偶数,元素处于偶数位置,列表奇数与其他元素。我一直在网上寻找解决方案,但在我看来都像中文,我无法理解这个过程。所以这就是我一直在尝试的:

split(List,Odd,Even):-odd(List,Oddlist,Evenlist).

odd([H|T],Oddlist,Evenlist):-even(T,[H|Oddlist],Evenlist).
odd([],_,_).

even([H|T],Oddlist,Evenlist):-odd(T,Oddlist,[H|Evenlist]).       
even([],_,_). 

但我得到的唯一 return 类似 Oddlist = _7132946 Evenlist = _26997888.

我不知道我做错了什么。我会很感激任何帮助。谢谢!

你的想法必须提炼...

首先,每种语言(不仅是 Prolog)都需要符号命名一致。所以我根据需要重命名了变量。

特定于 Prolog,有一种特定的方法来 'cons' 列表,源自应用于规则头的模式匹配。这同样适用于基本情况:我们必须提供将绑定调用方变量的空列表。

全部代码:

split(List,Odd,Even):-odd(List,Odd,Even).

odd([H|T],[H|Odd],Even):-even(T,Odd,Even).
odd([],[],[]).

even([H|T],Odd,[H|Even]):-odd(T,Odd,Even).       
even([],[],[]). 

CapelliC 的回答很完美。简单说明一下:

当你有这样的 Prolog 子句时:

foo([H|T], [H|Z]) :-
    foo(T, Z).

然后你可以这样称呼它:

?- foo([a,b,c], L).
from: foo([H|  T  ], [H|Z]) with H = a, T = [b,c], L = [a|Z]
call: foo([a|[b,c]], [a|Z])

然后导致递归调用:

call: foo([b,c], Z).
from: foo([H|  T  ], [H|Z]) with H = b, T = [c], L = [b|Z]
call: foo([b|[c]], [b|Z])

此时,你一开始做的列表,[a|Z]现在是[a|[b|Z]],也就是[a,b|Z].

因此,您在作为第二个参数传递的变量中创建一个列表,并将 H 放在列表的前面。您提供给递归调用的列表的其余部分。您将不断向列表末尾添加元素,直到第一个列表为空列表。届时,您也将结束新列表:

foo([], []).

在您的示例中,还有另一个谓词与第一个谓词相互递归:

foo([], [], []).
foo([H|T], [H|F], B) :-
    bar(T, F, B).

bar([], [], []).
bar([H|T], F, [H|B]) :-
    foo(T, F, B).

当然,这会"unzip"一个列表变成两个列表。

我知道这个 post 现在已经很旧了,但我想我也会添加我的解决方案,所以如果有人像我 15 分钟前一样,他们还有其他东西要看。这种方式以创建最终列表的方式向后构建列表。前 3 行是基本情况。

    split_odd_even([], [], []).
    split_odd_even([O], [O], []).
    split_odd_even([O,E], [O], [E]).
    split_odd_even([O,E|T], [O|OL], [E|EL]) :- split_odd_even(T, OL, EL).