从 Prolog 中的一个列表捕获值并添加到另一个列表
Capture values from one list in Prolog and add to another list
我正在尝试在 prolog 中开发代码以捕获频率为 0 的项目。查看示例,元组:
[[1,31],[2,0],[3,21],[4,0],[5,0]]
其中每个元素都是其他元素,每个元素有 2 个元素,因此应该捕获的元素是 2、4 和 5,频率为 0。下面的代码代表了这个想法:
match([],_).
match([[A,Y]|Tail],[A|Tail2]):- Y==0,match(Tail,[Tail2|A]),!.
match([[_,_]|Tail],X):- match(Tail,X).
传递了两个参数:包含一组目标值和频率的元组,
(["Target value", "frequency"], ["target value", "frequency"], ...]
第二个参数是一个变量,它接收目标元素。但是,我开发代码时的抽象并不正确,因为结果不是预期的那样。我一步一步地理解,修改了几件事,结果总是一样的......在任何情况下都返回一个只有 2 个元素的列表(即使只有一个频率为 0 的目标)。
具有 3 个频率目标的示例 0:
?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X).
X = [2|4].
本案例的预期结果:X = [2,4,5].
具有 1 个频率目标 0 的示例:
?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2|_9998].
此案例的预期结果:X = [2]。
有人可以帮助我吗?
你非常接近!只是两个小问题:
- 目前当一个空列表被传递给它时,你说结果可以是任何东西(
_
)。我非常怀疑这就是你想要的;空列表的输出也应该是一个空列表。
- 第二个子句中的递归调用不正确。您想要的结果是
A
后跟递归调用的结果 (Tail2
)。但是,出于某种原因,您编写了其中还包含 A 的递归调用。我不太清楚你是怎么做到的,但你应该自己得到 Tail2
。
另外,直接写在子句的开头就可以避免写Y==0
。生成的代码如下所示:
match([],[]).
match([[A,0]|Tail], [A|Tail2]) :- match(Tail, Tail2), !.
match([[_,_]|Tail], X) :- match(Tail, X).
?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X).
X = [2, 4, 5]
?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2]
您可以选择像这样用 DCG 描述结果列表:
match(Pairs,ZFs) :- % the items with frequency 0
phrase(zeros(Pairs),ZFs). % are described by zeros//1
zeros([]) --> % the empty list
[]. % contains no items
zeros([[I,0]|Is]) --> % if the frequency is 0
[I], % the item is in the list
zeros(Is). % the same for the remaining items
zeros([[I,F]|Is]) --> % if the frequency
{dif(F,0)}, % is not 0, the item isn't in the list
zeros(Is). % the same for the remaining items
因此,您 post 中的两个示例查询产生了所需的结果:
?- match([[1,31],[2,0],[3,21],[4,0],[5,0]],X).
X = [2,4,5] ? ;
no
?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2] ? ;
no
我正在尝试在 prolog 中开发代码以捕获频率为 0 的项目。查看示例,元组:
[[1,31],[2,0],[3,21],[4,0],[5,0]]
其中每个元素都是其他元素,每个元素有 2 个元素,因此应该捕获的元素是 2、4 和 5,频率为 0。下面的代码代表了这个想法:
match([],_).
match([[A,Y]|Tail],[A|Tail2]):- Y==0,match(Tail,[Tail2|A]),!.
match([[_,_]|Tail],X):- match(Tail,X).
传递了两个参数:包含一组目标值和频率的元组,
(["Target value", "frequency"], ["target value", "frequency"], ...]
第二个参数是一个变量,它接收目标元素。但是,我开发代码时的抽象并不正确,因为结果不是预期的那样。我一步一步地理解,修改了几件事,结果总是一样的......在任何情况下都返回一个只有 2 个元素的列表(即使只有一个频率为 0 的目标)。
具有 3 个频率目标的示例 0:
?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X).
X = [2|4].
本案例的预期结果:X = [2,4,5].
具有 1 个频率目标 0 的示例:
?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2|_9998].
此案例的预期结果:X = [2]。
有人可以帮助我吗?
你非常接近!只是两个小问题:
- 目前当一个空列表被传递给它时,你说结果可以是任何东西(
_
)。我非常怀疑这就是你想要的;空列表的输出也应该是一个空列表。 - 第二个子句中的递归调用不正确。您想要的结果是
A
后跟递归调用的结果 (Tail2
)。但是,出于某种原因,您编写了其中还包含 A 的递归调用。我不太清楚你是怎么做到的,但你应该自己得到Tail2
。
另外,直接写在子句的开头就可以避免写Y==0
。生成的代码如下所示:
match([],[]).
match([[A,0]|Tail], [A|Tail2]) :- match(Tail, Tail2), !.
match([[_,_]|Tail], X) :- match(Tail, X).
?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X).
X = [2, 4, 5]
?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2]
您可以选择像这样用 DCG 描述结果列表:
match(Pairs,ZFs) :- % the items with frequency 0
phrase(zeros(Pairs),ZFs). % are described by zeros//1
zeros([]) --> % the empty list
[]. % contains no items
zeros([[I,0]|Is]) --> % if the frequency is 0
[I], % the item is in the list
zeros(Is). % the same for the remaining items
zeros([[I,F]|Is]) --> % if the frequency
{dif(F,0)}, % is not 0, the item isn't in the list
zeros(Is). % the same for the remaining items
因此,您 post 中的两个示例查询产生了所需的结果:
?- match([[1,31],[2,0],[3,21],[4,0],[5,0]],X).
X = [2,4,5] ? ;
no
?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2] ? ;
no