Prolog读取键并打印对应于键的值

Prolog读取键并打印对应于键的值,prolog,repeat,Prolog,Repeat,我必须实现一个Prolog程序,它接受像[[1,a],[2,b],[1,c]]这样的列表,并在循环中请求一个键。如果用户输入1,则应打印[a,c],并要求用户输入下一个键,直到用户输入“退出” 我目前的计划: %Input: AssocList and Key. %Output: FindList which contains all Values associated with the Key in AssocList. as_find(AssocList, Key, FindList) :-

我必须实现一个Prolog程序,它接受像[[1,a],[2,b],[1,c]]这样的列表,并在循环中请求一个键。如果用户输入1,则应打印[a,c],并要求用户输入下一个键,直到用户输入“退出”

我目前的计划:

%Input: AssocList and Key.
%Output: FindList which contains all Values associated with the Key in AssocList.
as_find(AssocList, Key, FindList) :- 
    as_find(AssocList, Key, Acc, FindList).

as_find([], Key, Acc, Acc).
as_find([], Key, Acc, FindList) :- as_find([], Key, Acc, Acc).
as_find([[Key,D]|R], Key, Acc, FindList) :- my_append(D, Acc, NewFindList), as_find(R, Key, NewFindList, FindList).
as_find([[H,D]|R], Key, List, FindList) :- as_find(R, Key, List, FindList).

%Appends Elem to the given list and returns it in the other list.
my_append(Elem,[],[Elem]).
my_append(Elem,[H|R],[H|Z]) :- my_append(Elem,R,Z).  

%Asks for Keys and writes all Values associated with the keys.
as_search(List) :-
  repeat,
  write('Key?'),
  read(Key),   
  as_find(List, Key, FindList),
  write(FindList),
  Key == 'genug',
  !.
不幸的是,如果我使用“完成”以外的其他键,程序将以无限循环结束。你能帮忙吗

问候,,
hyperion

此程序使用故障驱动循环,您可以按目标启动程序<代码>?-开始。然后提示您添加列表。如果希望列表硬编码到程序中而不是作为用户输入,则可以更改此选项。然后我们进入循环,我们给出一个术语,例如
1。
然后系统将打印列表和循环中的匹配值。如果输入
stop.
程序将终止

start:-
   format("Enter list:\n",[]),
   read(List),
   enter(List).

enter(List):-
  format("Enter key or stop:\n",[]),
  read(X),
  test(X,List).

test(stop,_):-!.
test(X,List):-
  findall(Y,member([X,Y],List), Values),
  format("~w\n",[Values]),
  enter(List).
如果您输入的密钥在列表中不存在,则将打印一个空列表,并带您返回以重试

运行示例:

 ?- start.
 Enter list:
 |: [[1,a],[2,b],[1,c]].
 Enter key or stop:
 |: 1.
 [a,c]
 Enter key or stop:
 |: 2.
 [b]
 Enter key or stop:
 |: stop.

false.
使用repeat的不同版本:

start:-
  format("Enter list:\n",[]),
  read(List),
  format("Enter key or stop:\n",[]),
  repeat,
  read(X),
  (   X=stop->!;
    (     findall(Y,member([X,Y],List), Values),
          format("~w\n",[Values]),
          format("Enter key or stop:\n",[])),
          fail).

test/2
的子句主体中使用
fail
有什么好处吗?我想你不需要第二次失败。第一次失败取决于您希望目标成功还是默认失败。我将编辑它以删除它们。对!可能没有单一的最佳方式。但是保持简单是一个很好的默认设置,我想。嗨,你的程序运行得很好,但实际上我必须使用repeat,因为这是练习的目的。@hyperion使用repeat添加了另一个版本。