2010-05-18 4 views
5

У меня есть список слов и список связанных частей речевых тегов. Я хочу перебирать оба одновременно (согласованный индекс), используя каждый индексированный кортеж в качестве входных данных для функции .NET. Это самый лучший способ (он работает, но не чувствует себя естественно для меня):f # итерация по двум массивам, используя функцию из библиотеки C#

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 

ответ

13

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

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

+2

+1 для ||> оператора! –

+0

потрясающий. зачем ||> необходимо? почему не работает? –

+1

Я добавил некоторое объяснение относительно '||>' - кратко - он позволяет передавать два параметра функции справа, а '|>' задает только один параметр ('Seq.zip' принимает два параметра). –