f#, выполняющий итерации более чем двух массивов, с помощью функции из c# библиотеки

У меня есть список слов и список связанных тегов части речи. Я хочу выполнить итерации по обоим, одновременно (подобранный индекс) использующий каждый индексируемый кортеж, как введено для функции.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
5
задан Tomas Petricek 18 May 2010 в 00:15
поделиться

1 ответ

Ваш код мне кажется неплохим - большая его часть связана с некоторой загрузкой и инициализацией, так что вы мало что можете сделать, чтобы упростить эту часть. В качестве альтернативы Array.map2 вы можете использовать Seq.zip в сочетании с Seq.map - функция zip объединяет две последовательности в один, содержащий пары элементов с совпадающими индексами:

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

Поскольку функция 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

The ||> Оператор, используемый во второй версии, принимает кортеж, содержащий два значения, и передает их функции справа в качестве двух аргументов, что означает, что (a, b) ||> f означает fab . Оператор |> принимает только одно значение слева, поэтому (a, b) |> f будет означать f (a, b) (что будет работать, если функция f ожидает кортеж вместо двух параметров, разделенных пробелом).

Если вам нужно, чтобы леммы были массивом в конце, вам нужно добавить Array.ofSeq в конец конвейера обработки (все Seq работают с последовательностями, которые соответствуют IEnumerable )

Еще одна альтернатива - использовать выражения последовательности (вы можете использовать [| .. |] для построения массив напрямую, если это то, что вам нужно):

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

Использовать ли выражения последовательности или нет - это только личное предпочтение.В этом случае первый вариант кажется более лаконичным, но выражения последовательности могут быть более удобочитаемыми для людей, менее знакомых с такими вещами, как приложение частичных функций (в более короткой версии с использованием Seq.map )

13
ответ дан 18 December 2019 в 14:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: