2010-05-18 9 views
5

J'ai une liste de mots et une liste de parties de mots-clés associées. Je veux itérer sur les deux, simultanément (index correspondant) en utilisant chaque tuple indexé comme entrée d'une fonction .NET. Est-ce la meilleure façon (cela fonctionne, mais ne se sent pas naturel pour moi):f # itérer sur deux tableaux, en utilisant la fonction d'une bibliothèque 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 

Répondre

13

Votre code semble assez bon pour moi - la plupart d'entre elle traite de certaines chargement et l'initialisation, donc il n'y a pas grand-chose vous pourriez faire pour simplifier cette partie. En variante à Array.map2, vous pouvez utiliser Seq.zip combiné avec Seq.map - la fonction zip combine deux séquences en un seul qui contient des paires d'éléments avec des indices correspondant à:

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

Depuis lookup fonction prend un tuple que vous avez reçu comme un argument , vous pouvez écrire:

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

l'opérateur ||> utilisé dans la deuxième version prend un tuple contenant deux valeurs et les transmet à la fonction sur le côté droit comme deux arguments, ce qui signifie e au (a, b) ||> f signifie f a b. L'opérateur |> ne prend qu'une seule valeur sur la gauche, donc (a, b) |> f signifierait f (a, b) (ce qui fonctionnerait si la fonction f attendait un tuple au lieu de deux, espace séparé, paramètres).

Si vous avez besoin lemmas être un tableau à la fin, vous devrez ajouter Array.ofSeq à la fin du pipeline de traitement (toutes Seq fonctions fonctionnent avec des séquences qui correspondent à IEnumerable<T>)

Une alternative plus est d'utiliser des expressions de séquence (vous pouvez utiliser [| .. |] pour construire un tableau directement si c'est ce dont vous avez besoin):

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

que ce soit pour utiliser des expressions de séquence ou non - c'est juste une préférence personnelle. La première option semble plus succincte dans ce cas, mais les expressions de séquence peuvent être plus lisibles pour des personnes moins familières avec des choses comme l'application de fonction partielle (dans la version courte utilisant Seq.map)

+2

+1 pour l'opérateur ||>! –

+0

génial. pourquoi est-il nécessaire? pourquoi ne fonctionne pas? –

+1

J'ai ajouté quelques explications concernant '||>' - brièvement - cela vous permet de passer deux paramètres à la fonction sur la droite, alors que '|>' spécifie un seul paramètre ('Seq.zip' prend deux paramètres). –