【问题标题】:Difficulty with filtering two lists in SML在 SML 中过滤两个列表的困难
【发布时间】:2013-02-12 03:13:47
【问题描述】:

我正在尝试“双重”过滤两个列表,具体取决于痛苦地通过数据类型测试,而无需使用 HOP 进行递归。以下是我非常丑陋的解决方案尝试......

datatype 'a test = Test of ('a -> bool) * string;

fun foo xs lst = 
    let 
        fun foo_bar(x, ls) =
            let                
                val tests = (List.filter (fn (Test(f, str)) => (f x)) ls)
            in
                (List.map (fn (Test(f, str)) => str) tests)
            end 
    in
        (List.map (fn x => foo_bar(x, lst)) xs)
    end;

allPass: 'a list -> 'a test list -> 'a test list;

allPass [1, 2, 40, 150] [positive, even] 应该返回字符串"pos"

目前,我的函数正在返回一个嵌套列表:[["pos"], ["pos even"], ["pos even"], ["pos even"]]。有没有一种非递归的方法可以从这个结果中提取“pos”,还是我要以完全错误的方向解决这个问题?

【问题讨论】:

  • 也许您可以详细说明一下为什么您希望该函数只返回一个结果,而不是它现在返回的结果列表。此外,您还定义了 foo 函数,但在您的示例案例中使用了 allPass 函数。
  • 注意map和fold函数在顶层环境中是可用的,所以你不需要写List.map

标签: list sml


【解决方案1】:

你正朝着正确的方向前进,但你还没有完全到达那里。这就是我认为你想要的。

获取值列表和测试列表。返回 所有 值通过的测试名称列表。

好的,所以我们需要:

  1. 过滤测试列表。测试的谓词是所有值都必须通过。
  2. 提取通过的测试的名称。

好的,那么我们如何确定列表中的所有值是否都通过了一项测试?很简单,我们使用List.all

List.all    : ('a -> bool) -> 'a list -> bool

我们可以定义一个函数:

fun allPassesTest xs (Test(f,s)) = List.all f xs

当且仅当 xs 中的所有值都通过测试时,这将返回 true。现在我们根据这个函数过滤测试列表:

fun allPass xs tests = List.filter allPassesTest xs tests

但是,这会返回 'a test list 而不是 string list,因此您需要提取名称。

fun name (Test(f,s)) = s
fun allPass xs tests = map name (List.filter allPassesTest xs tests)

【讨论】:

    猜你喜欢
    • 2020-07-13
    • 1970-01-01
    • 2022-07-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2014-12-18
    • 2013-12-29
    相关资源
    最近更新 更多