簡體   English   中英

從 sml 中的 integer 對列表中返回偶數列表

[英]Return a list of even numbers from a list of integer pairs in sml

我有以下問題“給定一個 integer 對的列表,寫一個 function 以在 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]

任何幫助,將不勝感激。

我看到兩個明顯的問題。

如果第一個和第二個數字都是偶數,你做

#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可以實現為“只是”其他更通用函數的組合。

所以運行你當前的代碼,

- evenNumbers [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
val it = [6,6,3,5,7,9] : int list

表明您沒有捕獲所有偶數,並且您正在捕獲一些奇數。

function 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) 。同時,它將這個元素解構為它的部分xy 。所以在第二個 function 主體中,您可以表示isEven xisEven y

由於xy是否偶數總共有四種組合,因此很容易以類似復雜的 if-then-else 嵌套結束。 為此,我可能會做以下兩件事之一:

  1. 使用 case-of(並在pairs上遞歸調用evenNumbers ):

     fun evenNumbers [] =... | evenNumbers ((x,y)::pairs) = case (isEven x, isEven y) of... =>... |... =>...
  2. 將對列表展平為整數列表並filter它:

     fun flatten [] =... | flatten ((x,y)::pairs) =... val evenNumbers pairs =...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM