У меня есть список слов и список связанных тегов части речи. Я хочу выполнить итерации по обоим, одновременно (подобранный индекс) использующий каждый индексируемый кортеж, как введено для функции.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
Ваш код мне кажется неплохим - большая его часть связана с некоторой загрузкой и инициализацией, так что вы мало что можете сделать, чтобы упростить эту часть. В качестве альтернативы 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
)