【问题标题】:Categorising a list into two separate lists by type按类型将列表分为两个单独的列表
【发布时间】:2016-07-31 15:46:26
【问题描述】:

我对 Prolog 还是很陌生,并且在涉及列表的练习中遇到了困难:给定一个任意数据列表,将列表分成两个列表 - 一个包含整数值,一个包含实数值,然后忽略原始列表中的任何其他项目。

到目前为止,我已经写了以下内容:

isInteger(I, IntegerListHead):-
    integer(I),
    IntegerListHead is I.

isFloat(F, FloatListHead):-
    float(F),
    FloatListHead is F.

splitList([]).
splitList([H|T], [IntHead|IntList],[FloatHead|FloatList]):-
    isInteger(H, IntHead),
    isFloat(H, FloatHead),
    splitList(T, IntList, FloatList).

但是,我不确定为什么会出现某些错误:

?- splitList([1, 2.5, 6, 7.0, -1, -0.5], I, F).
ERROR: toplevel: Undefined procedure: splitList/3 (DWIM could not correct goal)

这个错误的通常嫌疑人似乎并非如此,但也许我错过了什么?

编辑:当我重新加载文件并再次运行时,我得到以下信息:

?- splitList([1, 2.5, 6, 7.0, -1, -0.5], I, F).
false.

【问题讨论】:

  • 您的splitList 谓词有一个基本情况子句的参数,但递归子句的三个参数。那是行不通的。基本情况也需要 3,并且需要为其他两个提供相应的值(在这种情况下,[] 不合适吗?)。您的错误看起来像 Prolog 没有定义 3 参数谓词,因此您一定没有加载正确显示的代码。
  • 您的错误消息确实包含一个错字:您正在调用splitList/1,这是一个简单的事实,但您收到关于splitList/3 的错误。这是不可能的。
  • 啊,抱歉 - 我复制了错误的行。让我快速编辑一下。

标签: list prolog


【解决方案1】:

您的基本案例需要更完整。它定义了统一列表为空时拆分列表的外观。所以基本情况应该是:

splitList([], [], []).   % Split lists are empty iff the unified list is empty

你的递归子句试图一次做所有事情,但在列表的头部进行整数与浮点测试的结合,导致必然错误的条件。换句话说,只有当H 既是浮点数又是整数时,以下情况才成立:

isInteger(H, IntHead),
isFloat(H, FloatHead)

您可以使用另一个子句将其拆分。生成的谓词将如下所示:

splitList([], [], []).
splitList([H|T], [IntHead|IntList], FloatList):-
    isInteger(H, IntHead),
    splitList(T, IntList, FloatList).
splitList([H|T], IntList, [FloatHead|FloatList]):-
    isFloat(H, FloatHead),
    splitList(T, IntList, FloatList).

最后,你真的不需要isIntegerisFloat。他们只会在确认它们的类型后对值进行不必要的“复制”。你只需要测试H

splitList([], [], []).
splitList([H|T], [H|IntList], FloatList):-
    integer(H),
    splitList(T, IntList, FloatList).
splitList([H|T], IntList, [H|FloatList]):-
    float(H),
    splitList(T, IntList, FloatList).


正如@CapelliC 所指出的,如果您的列表中包含非数字,这将失败。您可以采用以下方法以获得更通用的信息,这将跳过非数字元素。它很容易修改以将非数字元素保留在单独的列表中。
splitList([], [], []).
splitList([H|T], IntList, FloatList):-
    (   integer(H)
    ->  IntList = [H|Ints],
        FloatList = Floats
    ;   float(H)
    ->  IntList = Ints,
        FloatList = [H|Floats]
    ;   IntList = Ints,
        FloatList = Floats
    ),
    splitList(T, Ints, Floats).

【讨论】:

  • 你不会忘记跳过不是整数或浮点数的元素吗?
  • @CapelliC 确实,不错!我试图通过假设列表“表现良好”来保持简单。 :)
猜你喜欢
  • 2021-08-06
  • 2021-08-12
  • 2019-02-05
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
  • 2017-11-08
相关资源
最近更新 更多