解析Prolog中的列表列表

时间:2019-01-23 11:35:10

标签: prolog

我是Prolog的新手。考虑以下示例:

MainList =  [["A","a","0"],["A","b","0"],["B","a","0"],["B","b","0"],["A","a","1"],["B","b","1"],["C","c","1"],["C","a","0"]]
SubList = ["A","b","-']

MainList的格式:第一个索引应该是大写字母,第二个索引应该是小写字母,第三个索引应该是数字。 MainList可以包含其他格式(和长度),但我选择此格式是因为它更易于解释。我只想解释一下,每个子列表的索引都分为几类-每个列表的第一个元素属于category1,第二个元素属于category2,依此类推。 "-"符号表示我们确实知道该元素与其他元素的结合。

我要创建的关系应通过MainList并删除所有不遵循SubList的子列表。对于上面的示例,它应该返回:

Output =  [["A","b","0"],["B","a","0"],["C","c","1"],["C","a","0"]]

说明:"A""b"一起工作,因此应检查包含这些元素之一的每个子列表。如果它们都存在,那就没关系(没有重复项)。否则,如果仅存在其中之一,那就不行了,我们不应该将其插入Output列表中。

另一个示例(MainList与之前的示例有点不同):

MainList =  [["A","a","0"],["A","b","0"],["B","a","0"],["B","b","0"],["A","b","1"],["B","b","1"],["C","c","1"],["C","a","0"]]
SubList = ["C","a","0"]
Output = [["A","b","1"],["B","b","1"],["C","a","0"]]

我确实了解算法-我们应该遍历MainList的每个子列表,并检查input-sublist的连接是否正常工作,如果可以,我们将其插入Output列表中。问题是,我不知道如何正确实施它。如果子列表包含多于2个连接(如第二个示例所示),该怎么办?我应该如何区别于子列表?

编辑:我将尝试说明更多内容。每个元素的位置都很重要。每个地方代表一个不同的类别。例如,第一位可能代表大写字母,第二位代表小写字母,第三位代表数字(类别可能更多)。 我们得到一个sublist,它表示两个或多个元素之间的键。例如,我们在"A""b"之间有一个键:["A","b","-"]。我们应该遍历MainList的子列表,并检查每个子列表是否包含那些元素之一("A""b")。如果是这样,我们应该检查绑定是否正确。例如,如果我们有一个带有A的子列表(当然是在第一个索引中),那么我们应该转到第二个索引并检查"b"是否在那里。如果不存在,则不应将其插入Output列表中,否则将插入。例如,我们有一个债券["A","b","-"],并且进入了MainList的子列表,其子目录如下:["A","a","0"]["B","b","2"]。我们不会将这些列表插入Output中。但是,如果我们进入["A","b","1"]["A","b","2"]["B","a","1"]这样的子列表,我们会将这些列表插入Output

1 个答案:

答案 0 :(得分:2)

我写了一个代码,可以满足您给出的示例的输出条件,但是没有尝试其他情况或考虑代码的效率,因此您可以在上面进行改进。这是代码:

subList(List,SubL,Out):-
    (member("-",SubL),
     select("-",SubL,SubRem)
    ;
    \+ member("-",SubL),
    SubRem = SubL),
    findall(L,((member(L,List),checkEq(SubRem,L));
           (member(L,List),checkNeq(SubRem,L))),Out).

checkEq([],_).
checkEq([S|Rest],[E|List]):-
    S == E,
    checkEq(Rest,List).

checkNeq([],_).
checkNeq([S|Rest],List) :-
    \+ member(S,List),
    checkNeq(Rest,List).

说明:我所做的是,首先,我从子数组(如果存在)中删除了“-”字符,以便于计算。然后,我要么检查 SubList 中每个元素与 MainList 中所选 sublist 中的元素顺序是否一致的条件。如果失败,则检查所选子列表中是否没有 SubList 的元素。如果两项检查均失败,我将移至下一个子列表。使用findall / 3谓词,我找到满足这些条件之一的所有组合,并将它们组合在列表 Out

编辑:为checkEq谓词添加附加子句:

checkEq([S|Rest],[E|List]):-
    S \= E,
    member(S,List),
    checkEq([S|Rest],List).

所以最终版本是:

checkEq([],_).
checkEq([S|Rest],[E|List]):-
    S == E,
    checkEq(Rest,List).

checkEq([S|Rest],[E|List]):-
    S \= E,
    member(S,List),
    checkEq([S|Rest],List).