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