在Prolog中解析列表列表

在Prolog中解析列表列表,prolog,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可以包含其他格式(和长度),但我选择这种格

我不熟悉
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”
一起工作,因此应检查包含其中一个元素的每个子列表。如果它们都存在,那么就可以了(没有重复项)。否则,如果其中只有一个存在,则不正常,我们不应将其插入
输出
列表

另一个示例(
MainList
与前面的示例稍有不同):

我确实理解算法-我们应该检查
MainList
的每个子列表,检查输入子列表的连接是否正常,如果正常,我们将把它插入
输出
列表。问题是,我不知道如何正确地实施它。如果子列表包含超过2个连接(如第二个示例所示),该怎么办?我应该如何区别对待子列表

编辑:我会再解释一下。每个元素的位置都很重要。每个地方代表不同的类别。例如,第一位可能代表大字母,第二位代表小字母,第三位代表数字(可能有更多类别)。
我们得到一个子列表,它表示两个或多个元素之间的键。例如,我们在
“a”
“b”
之间有一个键:
[“a”,“b”,“-”]
。我们应该遍历
MainList
的子列表,并检查这些子列表中的每一个子列表是否包含这些元素中的一个(
“A”
“b”
)。如果有,我们应该检查债券是否正确。例如,如果我们有一个子列表有
a
(当然是在第一个索引中),那么我们应该转到第二个索引并检查
“b”
是否存在。如果不存在,我们不应该将其插入
输出
列表,否则我们将插入。例如,我们有一个键
[“a”,“b”,“-”]
,我们进入了
主列表的子列表,如下所示:
[“a”,“a”,“0”]
[“b”,“b”,“2”]
。我们不会将这些列表惰性化为
输出
。但是,如果我们得到了如下的子列表:“代码>(b)、“b”、“代码”>和“代码> > [ a ]、“b”、“2”]和<代码> > [ b ]、“a”、“1”] />代码>我们将把这些列表插入<代码>输出< /代码> .< /p> < p>我编写了一个满足您给出的示例的输出条件的代码,但是没有尝试其他情况或考虑代码的效率,所以你可以改进它。代码如下:

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).
说明:我所做的是,首先我从子数组中删除了“-”字符(如果存在的话),以使计算更容易。然后,我检查子列表中的每个元素是否与MainList的所选子列表中的元素顺序一致。如果失败,则检查所选子列表中是否不包含子列表的任何元素。如果两个检查都失败,我将移动到下一个子列表。使用findall/3谓词,我找到满足这些条件之一的所有组合,并将它们分组到列表中

编辑:为
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).

<>我写了一个代码,它满足了你给出的例子的输出条件,但是没有尝试其他的例子或者考虑代码的效率,所以你可以改进它。代码如下:

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).
说明:我所做的是,首先我从子数组中删除了“-”字符(如果存在的话),以使计算更容易。然后,我检查子列表中的每个元素是否与MainList的所选子列表中的元素顺序一致。如果失败,则检查所选子列表中是否不包含子列表的任何元素。如果两个检查都失败,我将移动到下一个子列表。使用findall/3谓词,我找到满足这些条件之一的所有组合,并将它们分组到列表中

编辑:为
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).

…删除所有不在
子列表之后的子列表
。我不清楚这是什么意思。在第一个示例中,
[“B”、“a”、“0”]
紧跟着
[“a”、“B”、“0”]
,它与
子列表
[“a”、“B”和
相匹配。在第二个示例中,输出不包括不在子列表后面的
[“A”、“A”、“0”]
[“C”、“A”、“0”]
@lower感谢您的回复。我所说的follow是指,如果子列表是
[“A”,“b”,“-”]
,那么我们在
A
b
之间有一个键<代码>[“B”、“a”、“0”]
不包含
a
B
,然后我们将其插入
输出
。但是
[“A”,“A”,“0”]
包含
A
,但不包含
b
,因此该键不成立。我会尝试编辑它。好的,谢谢。还要小心使用
。它与
“-”
完全不同
\u
是P中的匿名变量