"Subsetting" F# 中的字典
"Subsetting" a dictionary in F#
我是 F# 的初学者,我正在尝试编写一个函数来对给定列表的字典进行子集化,然后 return 结果。
我试过了,但是没用。
let Subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = dict.Clear
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.TryGetValue k) )
|> List.iter (fun s -> z.Add s)
|> List.iter (fun s -> z.Add s);;
--------------------------------------^^^
stdin(597,39): error FS0039: The field, constructor or member 'Add' is not defined
也许 F# 中有一个本机函数可以做到这一点?
谢谢
编辑
感谢@TheInnerLight 在下面的回答
你能不能再教我一点,告诉我如果我想 return 修改原始变量,我应该如何调整该函数?
(当然可以从我们调用该函数的地方,用一个临时变量调用它,然后重新分配)
您写了:
let z = dict.Clear
z
属于 unit->unit
类型,但您正在调用 z.Add
.
我怀疑你想写
let subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = Dictionary<'T,'U>() // create new empty dictionary
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.[k]) )
|> List.iter (fun s -> z.Add s)
z
TryGetValue
将在 F# 中 return 类型为 bool*'U
的东西,我怀疑如果已经通过 ContainsKey
过滤,您可能不想要它,所以您可能想要直接用dict.[k]
.
查找
请注意 Dictionary
是一个可变集合,因此如果您实际调用 dict.Clear()
,它不会 return 一个新的空字典,它会改变现有的清除所有元素。通常用于 key-value 关系的不可变 F# 数据结构是 Map
,请参阅 https://msdn.microsoft.com/en-us/library/ee353880.aspx 了解您可以使用 Map
.
执行的操作
这是地图版本(这是我推荐的解决方案):
let subset map subList =
subList
|> List.choose (fun k -> Option.map (fun v -> k,v) (Map.tryFind k map))
|> Map.ofList
编辑(回复关于修改输入变量的问题编辑):
可以在可变变量上使用破坏性更新运算符 <-
来更新现有字典。
选项 1:
let mutable dict = Dictionary<Key,Value>() // replace this with initial dictionary
let lst = [] // list to check against
dict <- sublist dict lst
同样,我的第一个函数可以更改为仅执行副作用(删除不需要的元素)。
选项 2:
let subset (d : System.Collections.Generic.Dictionary<'T,'U>) (sub_list : list<'T>) =
sub_list
|> List.filter (d.ContainsKey >> not)
|> List.iter (d.Remove >> ignore)
对于 F# 初学者,我真的不推荐选项 1,我真的不推荐选项 2。
函数式方法支持不可变值、纯函数等。这意味着您最好将函数视为定义数据转换,而不是定义要执行的指令列表。
因为 F# 是一种 multi-paradigm 语言,所以在早期阶段很容易退回到命令式,但是如果您强迫自己采用标准范式并且该语言的习语,即使这些习语一开始感觉很奇怪和不舒服。
像 Map
和 list
这样的不可变数据结构在共享数据以及提供良好的时间复杂度方面非常有效,因此在 F# 中工作时,这些确实是 go-to 集合。
我是 F# 的初学者,我正在尝试编写一个函数来对给定列表的字典进行子集化,然后 return 结果。
我试过了,但是没用。
let Subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = dict.Clear
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.TryGetValue k) )
|> List.iter (fun s -> z.Add s)
|> List.iter (fun s -> z.Add s);;
--------------------------------------^^^
stdin(597,39): error FS0039: The field, constructor or member 'Add' is not defined
也许 F# 中有一个本机函数可以做到这一点?
谢谢
编辑 感谢@TheInnerLight 在下面的回答 你能不能再教我一点,告诉我如果我想 return 修改原始变量,我应该如何调整该函数? (当然可以从我们调用该函数的地方,用一个临时变量调用它,然后重新分配)
您写了:
let z = dict.Clear
z
属于 unit->unit
类型,但您正在调用 z.Add
.
我怀疑你想写
let subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = Dictionary<'T,'U>() // create new empty dictionary
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.[k]) )
|> List.iter (fun s -> z.Add s)
z
TryGetValue
将在 F# 中 return 类型为 bool*'U
的东西,我怀疑如果已经通过 ContainsKey
过滤,您可能不想要它,所以您可能想要直接用dict.[k]
.
请注意 Dictionary
是一个可变集合,因此如果您实际调用 dict.Clear()
,它不会 return 一个新的空字典,它会改变现有的清除所有元素。通常用于 key-value 关系的不可变 F# 数据结构是 Map
,请参阅 https://msdn.microsoft.com/en-us/library/ee353880.aspx 了解您可以使用 Map
.
这是地图版本(这是我推荐的解决方案):
let subset map subList =
subList
|> List.choose (fun k -> Option.map (fun v -> k,v) (Map.tryFind k map))
|> Map.ofList
编辑(回复关于修改输入变量的问题编辑):
可以在可变变量上使用破坏性更新运算符 <-
来更新现有字典。
选项 1:
let mutable dict = Dictionary<Key,Value>() // replace this with initial dictionary
let lst = [] // list to check against
dict <- sublist dict lst
同样,我的第一个函数可以更改为仅执行副作用(删除不需要的元素)。
选项 2:
let subset (d : System.Collections.Generic.Dictionary<'T,'U>) (sub_list : list<'T>) =
sub_list
|> List.filter (d.ContainsKey >> not)
|> List.iter (d.Remove >> ignore)
对于 F# 初学者,我真的不推荐选项 1,我真的不推荐选项 2。
函数式方法支持不可变值、纯函数等。这意味着您最好将函数视为定义数据转换,而不是定义要执行的指令列表。
因为 F# 是一种 multi-paradigm 语言,所以在早期阶段很容易退回到命令式,但是如果您强迫自己采用标准范式并且该语言的习语,即使这些习语一开始感觉很奇怪和不舒服。
像 Map
和 list
这样的不可变数据结构在共享数据以及提供良好的时间复杂度方面非常有效,因此在 F# 中工作时,这些确实是 go-to 集合。