SML/NJ 在列表的元组列表中搜索
SML/NJ searching in list of tuples of list
我是 SML/NJ 的新手,有点迷路了。我一直在尝试实现一个函数,该函数将搜索其中包含一些列表的元组列表,例如:
val x = [(5, 2, [9 , 8, 7]), (3, 4, [6, 5, 0]), (11, 12, [8, 3, 1])]
一旦我的目标数字与元组元素 3 中的数字匹配,我希望我的函数将元组的第一个元素添加到新列表中。我已经尝试了几种实现方式,但到目前为止,其中 none 个都可以正常工作。
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
val a: int list = nil;
fun findNum(nil) = a | findNum (x: id list) =
let val tem = hd(x)
val theList = #3tem
val i = #1tem
fun findMatch(nil) = a | findMatch(tem) =
if (number = hd(theList)) then i::a
else findMatch (tl(theList))
in findNum(tl(x))
end;
findNum(b);
我知道它写得不好,这就是为什么它总是返回一个空列表。我觉得我需要做 "if else" 而不是 let/in/end 所以它将递归调用列表中的其余元组。我的问题是我不知道该怎么做,因为如果我使用 if/else 那么我就不能在函数内部声明一些值。我感谢任何建议或提示。
谢谢。
您可以从函数 member (x, xs)
开始,如果 x
是列表 xs
:
中的一个元素,该函数为真
fun member (x, xs) = List.exists (fn y => x = y) xs
基本情况是三元组列表为空。那么 x
不会出现在任何(不存在的)三元组的第三个元素中,结果列表为空。递归情况是通过对列表的第一个元素是三元组 (i,j,xs)
和列表的尾部 ts
进行模式匹配来实现的,并询问 x
是否是一个第三个元素的成员 xs
;如果是,return 元组的第一部分,i
:
fun find (x, []) = []
| find (x, (i,j,xs)::ts) =
if member (x, xs)
then i :: find (x, ts)
else find (x, ts)
使用高阶列表组合器 map
和 filter
的较短版本:
fun find (x, ts) = map #1 (filter (fn (i,j,xs) => member (x, xs)) ts)
这是我的实现,稍作改动:
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
fun findNum [] = []
| findNum (x::xs) =
let
val theList :int list = #3 (x :id)
val i : int = #1 x
fun findMatch [] = false
| findMatch (y::ys) = if (number = y) then true
else findMatch ys
in
if (findMatch theList = true) then i ::(findNum xs)
else (findNum xs)
end;
示例:
- findNum b;
val it = [5,11] : int list
我是 SML/NJ 的新手,有点迷路了。我一直在尝试实现一个函数,该函数将搜索其中包含一些列表的元组列表,例如:
val x = [(5, 2, [9 , 8, 7]), (3, 4, [6, 5, 0]), (11, 12, [8, 3, 1])]
一旦我的目标数字与元组元素 3 中的数字匹配,我希望我的函数将元组的第一个元素添加到新列表中。我已经尝试了几种实现方式,但到目前为止,其中 none 个都可以正常工作。
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
val a: int list = nil;
fun findNum(nil) = a | findNum (x: id list) =
let val tem = hd(x)
val theList = #3tem
val i = #1tem
fun findMatch(nil) = a | findMatch(tem) =
if (number = hd(theList)) then i::a
else findMatch (tl(theList))
in findNum(tl(x))
end;
findNum(b);
我知道它写得不好,这就是为什么它总是返回一个空列表。我觉得我需要做 "if else" 而不是 let/in/end 所以它将递归调用列表中的其余元组。我的问题是我不知道该怎么做,因为如果我使用 if/else 那么我就不能在函数内部声明一些值。我感谢任何建议或提示。
谢谢。
您可以从函数 member (x, xs)
开始,如果 x
是列表 xs
:
fun member (x, xs) = List.exists (fn y => x = y) xs
基本情况是三元组列表为空。那么 x
不会出现在任何(不存在的)三元组的第三个元素中,结果列表为空。递归情况是通过对列表的第一个元素是三元组 (i,j,xs)
和列表的尾部 ts
进行模式匹配来实现的,并询问 x
是否是一个第三个元素的成员 xs
;如果是,return 元组的第一部分,i
:
fun find (x, []) = []
| find (x, (i,j,xs)::ts) =
if member (x, xs)
then i :: find (x, ts)
else find (x, ts)
使用高阶列表组合器 map
和 filter
的较短版本:
fun find (x, ts) = map #1 (filter (fn (i,j,xs) => member (x, xs)) ts)
这是我的实现,稍作改动:
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
fun findNum [] = []
| findNum (x::xs) =
let
val theList :int list = #3 (x :id)
val i : int = #1 x
fun findMatch [] = false
| findMatch (y::ys) = if (number = y) then true
else findMatch ys
in
if (findMatch theList = true) then i ::(findNum xs)
else (findNum xs)
end;
示例:
- findNum b;
val it = [5,11] : int list