想象一下像L = [1, 4, _, 5, _]
这样的列表
如果我想检查4
是否是此列表的成员,我可以执行以下操作:member(4, L)
。这将返回True,因为此列表中有4
。但是,对于我检查的每个元素,它使用member / 2返回true。当然,这是因为匿名变量可以与任何东西匹配。所以它总会返回True。我想知道是否有一种方法可以从列表L
中删除所有匿名变量。因此NewList
为[1, 4, 5]
。
答案 0 :(得分:1)
为了检查某些项目是否在包含匿名变量的列表中,您首先需要(暂时)从该列表中删除所有匿名变量。为此,您可以使用内置谓词subtract/3
和var/1
。
subtract/3
:第一个元素是您要检查的列表,第二个元素是包含要从列表中删除的元素的列表,第三个元素是结果列表。
var/1
:只包含一个元素(X),如果X是未绑定的变量,则返回True
。
在这种情况下,我们希望subtract
在True
时返回var(X)
的每个元素(X)var(_)
。在代码中,这写为subtract/3
。
现在我们只需填写subtract(L, [var(_)], NewList).
这样的谓词:NewList
member/2
现在只存储绑定变量,而change
现在可以按预期工作。
答案 1 :(得分:1)
除了从列表中删除变量然后使用member/2
之外,您还可以选择实现自己的谓词来描述member/2
- 类似于非变量元素的关系:
nonvarmember(X,[Y|_]) :-
nonvar(Y), % only try to unify with X if Y is not a variable
X=Y.
nonvarmember(X,[_Y|Ys]) :-
nonvarmember(X,Ys).
现在让我们看看这个谓词的工作原理:
?- nonvarmember(4,[1,4,_,5,_]).
true ;
false.
?- nonvarmember(4,[1,_,_,5,_]).
false.
?- nonvarmember(4,[1,4,_,5,_,Z]).
true ;
false.
但是,第一个参数仍然可以是变量:
?- nonvarmember(X,[1,4,_,5,_,Z]).
X = 1 ;
X = 4 ;
X = 5 ;
false.
?- nonvarmember(X,[_,_,_]).
false.
但请注意,如果首先从列表中删除变量元素并随后使用member/2
或使用nonvarmember/2
,则会遇到以下问题:List-elements在您检查成员资格未被计算后实例化,因此可能导致不健全的答案。以下示例说明了问题:
?- A=4, nonvarmember(4,[A,B,C]).
A = 4 ;
false.
?- nonvarmember(4,[A,B,C]), A=4.
false.
答案 2 :(得分:1)
如果是Swi-Prolog(至少),您可以使用include / 3和exclude / 3谓词来过滤列表。您可以将这些谓词与var / 1和nonvar / 1一起使用,以从列表中删除变量。
在您的特定情况下,检查4是否属于列表[1,4,_,5,_]可以按如下方式进行:
Y-1 Kandydaci = CALCULATE(
distinctcount(getDataForTeb[ID_DANE_OSOBOWE]);
DATESBETWEEN(
getDataForTeb[Złożenie podania];
DATE(YEAR(now())-1;4;1);
IF(DATE(YEAR(NOW())-1;MONTH(NOW());DAY(NOW()))<=DATE(YEAR(NOW())-1;11;30);
DATE(YEAR(NOW())-1;MONTH(NOW());DAY(NOW()));DATE(YEAR(NOW())-1;11;30)));
ISBLANK(getDataForTeb[REZYGNACJA_DATA]))
Y-1 Kandydaci cumulative = CALCULATE(
DISTINCTCOUNT(getDataForTeb[ID_DANE_OSOBOWE]);
FILTER(
ALL (getDataForTeb);
AND (
getDataForTeb[Złożenie podania] <= MAX(getDataForTeb[Złożenie podania])-364;
AND (
getDataForTeb[Złożenie podania] <= DATE(YEAR(NOW())-1; 11; 30);
getDataForTeb[Złożenie podania] >= DATE(YEAR(NOW())-1; 4; 1)
)
)
);
ISBLANK(getDataForTeb[REZYGNACJA_DATA])
)