我是F#的新手,并试图在F#中重写我们的一个应用程序,试图在整个过程中学习它,我在整理列表时遇到了一些麻烦。我已经搜索并找到了几个答案,但我似乎无法让它们中的任何一个起作用。
我的数据类型是val regEntries:RegistryKey列表
我希望它只是一个列表。
以下是我的代码:
namespace DataModule
module RegistryModule =
open Microsoft.Win32
let regEntries =
["SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"; "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"]
|> List.map (fun x -> Microsoft.Win32.Registry.LocalMachine.OpenSubKey(x))
|> List.map(fun k -> List.ofArray(k.GetSubKeyNames()) |> List.map (fun x -> k.OpenSubKey(x)) |> List.filter (fun x -> x.GetValue("ProductId") <> null))
答案 0 :(得分:8)
尝试以下
let regEntries =
["SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"; "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"]
|> Seq.map (fun x -> Microsoft.Win32.Registry.LocalMachine.OpenSubKey(x))
|> Seq.map(fun k ->
(k.GetSubKeyNames())
|> Seq.map (fun x -> k.OpenSubKey(x))
|> Seq.filter (fun x -> x.GetValue("ProductId") <> null)))
|> Seq.concat
|> List.ofSeq
Seq.concat
方法对于将T list list
转换为T list
非常有用。请注意,我将大量List.
来电转为Seq.
次来电。似乎没有必要在最后创建一个实际的list
因此我将其保持为简单的seq
答案 1 :(得分:5)
使用各种map
和filter
函数绝对是一种选择 - 它的效果很好(这也是学习函数抽象的好方法)。
然而,你也可以使用序列理解,这是一个很好的语法糖,使得编写这些任务更容易(在我看来)。要做与Jared在答案中发生的事情相同的事情,你可以写:
let subKeys =
[@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"; //"
@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"] // "
let regEntries =
[ for subKey in subKeys do
let k = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(subKey)
for name in k.GetSubKeyNames() do
let x = k.OpenSubKey(name)
if x.GetValue("ProductId") <> null then
yield x ]
嵌套只是变成嵌套的for
循环,并使用if
表示过滤 - 以生成可以使用yield
的序列的新值以及表达式包含在中的事实方括号使其成为列表理解。
答案 2 :(得分:0)
请注意,如果您发现此问题正在寻找一种基本的展平方法:
let flatten (source : 'T seq seq) :'T seq =
System.Linq.Enumerable.SelectMany(source, id)
这是使用 F# id
function 对 .net SelectMany
的基本调用。