2010-05-18 8 views
5

Mam listę słów i listę powiązanych części tagów mowy. Chcę iterować na oba jednocześnie (dopasowany indeks), używając każdej indeksowanej krotki jako wejścia do funkcji .NET. Jest to najlepszy sposób (to działa, ale nie czują się naturalne dla mnie):f # iteracja na dwóch tablicach, przy użyciu funkcji z biblioteki 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 

Odpowiedz

13

Twój kod wygląda całkiem dobrze mi - większość z nich zajmuje się jakimś załadunku i inicjowania, więc nie ma wiele możesz zrobić, aby uprościć tę część. Alternatywnie do Array.map2, można użyć Seq.zip połączeniu z Seq.map - funkcja zip łączy dwie sekwencje w jeden, który zawiera pary elementów z pasującymi indeksów:

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

Od lookup funkcja przyjmuje krotki, że masz jako argument , można napisać:

// 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 

operator ||> stosowany w drugiej wersji trwa krotki zawierający dwie wartości i przekazuje je do funkcji po prawej stronie jako dwa argumenty, co oznacza, th pod adresem (a, b) ||> f oznacza f a b. Operator |> przyjmuje tylko jedną wartość po lewej, więc (a, b) |> f oznaczałoby f (a, b) (co zadziałałoby, gdyby funkcja f oczekiwała krotki zamiast dwóch, oddzielonych spacjami, parametrów).

Jeśli potrzebujesz lemmas być tablicą na koniec, trzeba dodać Array.ofSeq na końcu rurociągu przetwarzania (wszystkie Seq funkcje działają z sekwencji, które odpowiadają IEnumerable<T>)

Kolejny alternatywny jest użycie wyrażeń sekwencji (można użyć [| .. |] skonstruować tablicę bezpośrednio, czy to, co trzeba):

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

czy używać wyrażeń sekwencji lub nie - to tylko osobiste preferencje. Pierwsza opcja wydaje się bardziej zwięzła w tym przypadku, ale wyrażenia sekwencji mogą być bardziej czytelne dla osób mniej zaznajomionych z aplikacjami o częściowym działaniu (w krótszej wersji z użyciem Seq.map)

+2

+1 dla operatora ||>! –

+0

niesamowite. dlaczego ||> jest konieczne? dlaczego nie |> działa? –

+1

Dodałem wyjaśnienie dotyczące '||>' - krótko - pozwala przekazać dwa parametry do funkcji po prawej stronie, natomiast '|>' określa tylko jeden parametr ('Seq.zip' przyjmuje dwa parametry). –

Powiązane problemy