Return sml 中整数对列表中的偶数列表
Return a list of even numbers from a list of integer pairs in sml
我有以下问题“给定整数对列表,将函数写入 return sml 中该列表中的偶数列表”。
这是我到目前为止所取得的成就
val x = [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
fun isEven(num : int) =
if num mod 2 = 0 then num else 0;
fun evenNumbers(list : (int * int) list) =
if null list then [] else
if isEven(#1 (hd list)) <> 0
then if isEven(#2 (hd list)) <> 0
then #1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
else []
else if isEven(#2 (hd list)) <> 0
then #1 (hd list) :: evenNumbers(tl list)
else [];
evenNumbers(x);
结果应该是这样的[6,2,4,6,8,10]
如有任何帮助,我们将不胜感激。
所以运行你当前的代码,
- evenNumbers [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
val it = [6,6,3,5,7,9] : int list
表明您没有捕捉到所有偶数,而是捕捉到了一些奇数。
函数 isEven
听起来很像你想要这样的类型 int -> bool
:
fun isEven n =
n mod 2 = 0
我不想解决您当前解决方案的逻辑错误,而是想提出一种语法上更简单的方法,即使用模式匹配和更少的显式类型注释。这种解决方案的一个基础可能如下所示:
fun evenNumbers [] = ...
| evenNumbers ((x,y)::pairs) = ...
使用模式匹配是 if-then-else 的替代方法:[]
模式等效于 if null list ...
,而 (x,y)::pairs
模式在输入列表非空时匹配(包含至少一个元素,即 (x,y)
。同时,它将这个元素解构为 x
和 y
部分。所以在第二个函数体中你可以表达 isEven x
和 isEven y
.
由于 x
和 y
是否偶数一共有四种组合,这很容易导致类似复杂的 if-then-else 嵌套。为此,我可能会做以下两件事之一:
用例(并在 pairs
上递归调用 evenNumbers
):
fun evenNumbers [] = ...
| evenNumbers ((x,y)::pairs) =
case (isEven x, isEven y) of
... => ...
| ... => ...
将对列表展平为整数列表,然后filter
它:
fun flatten [] = ...
| flatten ((x,y)::pairs) = ...
val evenNumbers pairs = ...
我看到两个明显的问题。
如果第一个和第二个数字都是偶数,就可以
#1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
将第一个数字相加两次并忽略第二个。
如果第一个数字是奇数,第二个数字是偶数,那么你就是
#1 (hd list) :: evenNumbers(tl list)
它会添加您知道的奇数并忽略您知道的偶数。
使用选择器和条件进行编程会很快变得复杂(如您所见)。
有了模式匹配,你可以这样写
fun evenNumbers [] = []
| evenNumber ((x,y)::xys) = ...
并降低使用错误选择器的风险。
不过这样还是逻辑复杂,还有更好的办法
考虑从数字列表中过滤出奇数而不是对的更简单的问题。
如果将输入转换为这样的列表,则只需解决那个更简单的问题(并且很有可能您已经在之前的练习中解决了非常相似的问题)。
练习:实现这个转换。它的类型将是 ('a * 'a) list -> 'a list
.
另外,如果你的 isEven
产生真值(如果你问某人,“36 是偶数吗?”,“36”是一个非常奇怪的答案)。
fun isEven x = x mod 2 = 0
现在,evenNumbers
可以“仅”作为其他更通用的函数的组合来实现。
我有以下问题“给定整数对列表,将函数写入 return sml 中该列表中的偶数列表”。
这是我到目前为止所取得的成就
val x = [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
fun isEven(num : int) =
if num mod 2 = 0 then num else 0;
fun evenNumbers(list : (int * int) list) =
if null list then [] else
if isEven(#1 (hd list)) <> 0
then if isEven(#2 (hd list)) <> 0
then #1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
else []
else if isEven(#2 (hd list)) <> 0
then #1 (hd list) :: evenNumbers(tl list)
else [];
evenNumbers(x);
结果应该是这样的[6,2,4,6,8,10]
如有任何帮助,我们将不胜感激。
所以运行你当前的代码,
- evenNumbers [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
val it = [6,6,3,5,7,9] : int list
表明您没有捕捉到所有偶数,而是捕捉到了一些奇数。
函数 isEven
听起来很像你想要这样的类型 int -> bool
:
fun isEven n =
n mod 2 = 0
我不想解决您当前解决方案的逻辑错误,而是想提出一种语法上更简单的方法,即使用模式匹配和更少的显式类型注释。这种解决方案的一个基础可能如下所示:
fun evenNumbers [] = ...
| evenNumbers ((x,y)::pairs) = ...
使用模式匹配是 if-then-else 的替代方法:[]
模式等效于 if null list ...
,而 (x,y)::pairs
模式在输入列表非空时匹配(包含至少一个元素,即 (x,y)
。同时,它将这个元素解构为 x
和 y
部分。所以在第二个函数体中你可以表达 isEven x
和 isEven y
.
由于 x
和 y
是否偶数一共有四种组合,这很容易导致类似复杂的 if-then-else 嵌套。为此,我可能会做以下两件事之一:
用例(并在
pairs
上递归调用evenNumbers
):fun evenNumbers [] = ... | evenNumbers ((x,y)::pairs) = case (isEven x, isEven y) of ... => ... | ... => ...
将对列表展平为整数列表,然后
filter
它:fun flatten [] = ... | flatten ((x,y)::pairs) = ... val evenNumbers pairs = ...
我看到两个明显的问题。
如果第一个和第二个数字都是偶数,就可以
#1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
将第一个数字相加两次并忽略第二个。
如果第一个数字是奇数,第二个数字是偶数,那么你就是
#1 (hd list) :: evenNumbers(tl list)
它会添加您知道的奇数并忽略您知道的偶数。
使用选择器和条件进行编程会很快变得复杂(如您所见)。
有了模式匹配,你可以这样写
fun evenNumbers [] = []
| evenNumber ((x,y)::xys) = ...
并降低使用错误选择器的风险。
不过这样还是逻辑复杂,还有更好的办法
考虑从数字列表中过滤出奇数而不是对的更简单的问题。
如果将输入转换为这样的列表,则只需解决那个更简单的问题(并且很有可能您已经在之前的练习中解决了非常相似的问题)。
练习:实现这个转换。它的类型将是 ('a * 'a) list -> 'a list
.
另外,如果你的 isEven
产生真值(如果你问某人,“36 是偶数吗?”,“36”是一个非常奇怪的答案)。
fun isEven x = x mod 2 = 0
现在,evenNumbers
可以“仅”作为其他更通用的函数的组合来实现。