如果在列表中找到字符串,则PROLOG存储列表的第n个元素

时间:2018-04-14 10:58:28

标签: prolog

我想做的是:

fromHistory / 2

fromHistory(HL,FL)

如果列表包含单词" ate"

,则FL是列表的第3个元素

如果列表包含所有单词,则FL是列表的第4个元素["你","可以","有"]

谓词应该循环到列表HL列表中,如果其中一个列表包含上面的单词,它应该根据找到的单词附加第3 /第4个元素,否则它不应该是#t; t得到任何东西。

?- fromHistory([[i,ate,x], [you,can,have,y]], FL).
FL = [x, y] ;
false.

?- fromHistory([[this,is,a,useless,input], [i,ate,x], [another,input],
                [another,useless,input], ["Ok"], [you,can,have,y]], FL).
FL = [x, y] ;
false.

x和y并不总是在列表的末尾,而是在[" ate"]和["你"," can"之后的字符串, "具有"]

我尝试使用here

中的查找版本
find(X,Y,[X,Y|Tail]):-
   !.
find(X,Y,[_|Tail]):-
   find(X,Y,Tail).


foodFromHistory(HL1, FL):-
    flatten(HL1, HL),
    find(ate, FL1, HL),
    find([you, can, have], FL2, HL),
    FL = [FL1|FL2].

然而,它不能与[你,可以,有]并且返回false,它也不会在整个列表上工作,而是仅在第一次出现时。

3 个答案:

答案 0 :(得分:1)

根据经验,如果你需要逐个元素地处理一些事物的列表,首先要清楚地知道如何为每个元素做些什么(在这种情况下,这些"元素&#34 ;是输入短语)并实现和测试,而不用担心整个问题。所以:

  

如果列表包含单词" ate"

,则FL是列表的第3个元素      

如果列表包含所有单词,则FL是列表的第4个元素["你","可以","有"]

这不是一个非常好的规范,但是这里有一个实现,你可以独立于更大的问题进行测试和调整:

input_food([_Somebody, ate, Food], Food).
input_food(Input, Food) :-
    append(_Something, [you, can, have, Food | _Rest], Input).

就是这样!您有两个要求,每个要求描述列表上的简单模式匹配。因此,Prolog实现可以是两个子句,每个子句在列表上实现简单的模式匹配。

让我们测试一下:

?- input_food([i, ate, x], Food).
Food = x ;
false.

?- input_food([you, ate, x], Food).
Food = x ;
false.

?- input_food([ok, you, can, have, strawberries], Food).
Food = strawberries ;
false.

?- input_food([this, sentence, no, food], Food).
false.

好的,我们现在需要做的就是迭代输入列表并收集input_food/2给出的每个输入的食物(如果有的话)。这是标准的:

inputs_foods([], []).
inputs_foods([I|Is], [Food|Fs]) :-
    input_food(I, Food),
    inputs_foods(Is, Fs).
inputs_foods([I|Is], Fs) :-
    \+ input_food(I, _Food),
    inputs_foods(Is, Fs).

似乎主要做你想做的事情:

?- inputs_foods([[this,is,a,useless,input], [i,ate,x], [another,input],
                [another,useless,input], ["Ok"], [you,can,have,y]], FL).
FL = [x, y] ;
false.

答案 1 :(得分:0)

我不完全理解prediacte应该如何工作,像[some,input,i,ate,x,some,other,input]这样的数组呢,它应该将x附加到列表中吗?

您可以尝试创建自己的列表,例如H1 = [i,ate,X|_],H2 = [you,can,have,Y|_],然后递归遍历HL的成员并比较它们并使您的解决方案用X或Y统一它们。

编辑

我为[i,ate,x]制作了一些东西,现在你必须对[你,可以,有,y]采取类似的方法。

方法是检查列表[i,ate,X]是否是HL的当前成员的子列表,如果是,我们可以将X添加到我们的FL集合中。检查这是否是您所期望的:)

fromHistory(HL,FL) :-
    findAnswers(HL,[],FL).

findAnswers([],Answers,Answers).
findAnswers([H|HL],FL,Answers) :-
       (isSublist([i,ate,X],H) -> append(FL,[X],FL2); FL2 = FL),
       findAnswers(HL,FL2,Answers).

isSublist(SL, L) :-
    append([_,SL,_],L).

答案 2 :(得分:0)

您的问题的解决方案可能是:

solve(L,FL,FLO):-
    member("ate",L),
    \+consequent(L),
    nth1(3,L,E),
    append(FL,[E],FLO).

solve(L,FL,FLO):-
    \+member("ate",L),
    consequent(L),
    nth1(4,L,E),
    append(FL,[E],FLO).


consequent(L):-
    nth1(P,L,"you"),
    P1 is P+1,
    nth1(P1,L,"can"),
    P2 is P+2,
    nth1(P2,L,"have").

fromHistory([],L,L).
fromHistory([H|T],L,FL):-
    solve(H,L,FLO),
    fromHistory(T,FLO,FL).

首先,检查ate是否在列表中,you can have不在其中。然后,您可以使用nth/3找到所需的元素,并使用append/3将其附加到列表中。类似的情况是,您在列表中找到you can haveate不在其中。当您在列表中同时包含ateyou can have时,您必须决定要执行的操作。在此实现中,谓词失败。

查询:

?- fromHistory([["you","can","have","hallo","at"],["ate","str1","str2"]],["test","aa"],L).
L = ["test", "aa", "hallo", "str2"]