我有一个类型列表(string * (int * int)) list.我希望能够搜索列表,通过它的string标识符找到正确的元素,对其中一个进行计算ints,然后返回完整的修改后的列表.
例:
给出一个清单
let st = [("a1",(100,10)); ("a2",(50,20)); ("a3",(25,40))]
我正在尝试创建一个函数,它获取元素之一并从ints元组中的一个中减去数字.
get ("a2",10) st
//Expected result: st' = [("a1",(100,10)); ("a2",(40,20)); ("a3",(25,40))]
Run Code Online (Sandbox Code Playgroud)
我觉得我差不多了,但是我对以下功能感到困惑:
let rec get (a,k) st =
match st with
| (a',(n',p'))::rest when a'=a && k<=n' -> (n'-k,p')::rest
| (a',(n',p'))::rest -> (n',p')::get (a,k) rest
| _ -> failwith "Illegal input"
Run Code Online (Sandbox Code Playgroud)
这将返回[("a2",(40,20)); ("a3",(25,40))]并因此缺少第一个a1元素.任何提示?
列表是不可变的,因此如果您想"更改一个元素",您实际上是在创建一个包含一个元素转换的新列表.像这样进行转换的最简单方法是使用List.map函数.我会写一些类似的东西:
let updateElement key f st =
st |> List.map (fun (k, v) -> if k = key then k, f v else k, v)
Run Code Online (Sandbox Code Playgroud)
updateElement是一个带有键,更新功能和输入的助手.它返回列表,其中具有给定键的元素已使用给定函数进行转换.例如,要增加与之关联的第一个数字a2,您可以编写:
let st = [("a1",(100,10)); ("a2",(50,20)); ("a3",(25,40))]
st |> updateElement "a2" (fun (a, b) -> a + 10, b)
Run Code Online (Sandbox Code Playgroud)