f#使用ac#library中的函数迭代两个数组

And*_*ney 5 arrays iteration f#

我有一个单词列表和一个相关的词性标签列表.我想使用每个索引元组作为.NET函数的输入同时迭代两个(匹配索引).这是最好的方式(它有效,但对我来说不自然):

let taggingModel = SeqLabeler.loadModel(lthPath + 
                      "models\penn_00_18_split_dict.model");
let lemmatizer = new Lemmatizer(lthPath + "v_n_a.txt")
let input = "the rain in spain falls on the plain"

let words = Preprocessor.tokenizeSentence( input )
let tags = SeqLabeler.tagSentence( taggingModel, words )
let lemmas = Array.map2 (fun x y -> lemmatizer.lookup(x,y)) words tags
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 13

你的代码看起来对我很好 - 大部分代码都处理一些加载和初始化,所以你没有太多的东西来简化那部分.或者Array.map2,您可以Seq.zip结合使用Seq.map- 该zip函数将两个序列组合成一个序列,其中包含具有匹配索引的元素对:

let lemmas = Seq.zip words tags 
          |> Seq.map (fun (x, y) -> lemmatizer.lookup (x, y)) 
Run Code Online (Sandbox Code Playgroud)

由于lookup函数采用了你作为参数得到的元组,你可以写:

// standard syntax using the pipelining operator
let lemmas = Seq.zip words tags |> Seq.map lemmatizer.lookup

// .. an alternative syntax doing exactly the same thing
let lemmas = (words, tags) ||> Seq.zip |> Seq.map lemmatizer.lookup
Run Code Online (Sandbox Code Playgroud)

||>第二个版本中使用的运算符采用包含两个值的元组,并将它们作为两个参数传递给右侧的函数,这意味着这(a, b) ||> f意味着f a b.该|>运营商需要在左侧只有一个值,所以(a, b) |> f将意味着f (a, b)(这工作,如果函数f预期的元组而不是两个,空格隔开,参数).

如果你需要lemmas在最后成为一个数组,你需要添加Array.ofSeq到处理管道的末尾(所有Seq函数都使用序列,对应于IEnumerable<T>)

还有一种方法是使用序列表达式([| .. |]如果你需要的话,你可以直接构造一个数组):

let lemmas = [| for wt in Seq.zip words tags do // wt is tuple (string * string)
                  yield lemmatizer.lookup wt |] 
Run Code Online (Sandbox Code Playgroud)

是否使用序列表达式 - 这只是个人偏好.在这种情况下,第一个选项似乎更简洁,但对于不熟悉部分函数应用程序(在较短版本中使用Seq.map)的人来说,序列表达式可能更具可读性