2010-05-18 15 views
5

Tengo una lista de palabras y una lista de las etiquetas de parte de la oración asociadas. Quiero iterar sobre ambos, simultáneamente (índice emparejado) usando cada tupla indexada como entrada a una función .NET. ¿Es ésta la mejor manera (que funciona, pero no se siente natural para mí):f # iteración sobre dos matrices, utilizando la función de una biblioteca 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 

Respuesta

13

Su código es bastante bueno para mí - la mayor parte de los que se ocupa con un poco de carga e inicialización, así que no hay mucho podrías hacer para simplificar esa parte. Alternativamente a Array.map2, podría utilizar Seq.zip combinarse con Seq.map - la función zip combina dos secuencias en una sola que contiene pares de elementos con índices que emparejan:

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

Desde lookup función toma una tupla que tienes como un argumento , se podría escribir:

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

el operador ||> utilizado en la segunda versión toma una tupla que contiene dos valores y los pasa a la función en el lado derecho como dos argumentos, lo que significa º en (a, b) ||> f significa f a b. El operador |> toma solo un valor a la izquierda, por lo que (a, b) |> f significa f (a, b) (que funcionaría si la función f esperaba una tupla en lugar de dos, espacios separados, parámetros).

Si necesita lemmas a ser un array al final, tendrá que añadir Array.ofSeq hasta el final de la canalización de procesamiento (todos Seq funciones trabajan con secuencias que corresponden a IEnumerable<T>)

una alternativa más es el uso de expresiones de secuencia (se puede utilizar [| .. |] para construir una matriz directamente si eso es lo que necesita):

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

si se debe usar expresiones de secuencia o no - eso es sólo una preferencia personal. La primera opción parece ser más sucinta en este caso, pero las expresiones de secuencia pueden ser más legibles para personas menos familiarizadas con cosas como la aplicación de función parcial (en la versión más corta usando Seq.map)

+2

+1 para operador ||>! –

+0

impresionante. ¿por qué es ||> necesario? ¿Por qué no funciona? –

+1

Agregué algunas explicaciones con respecto a '||>' - brevemente - le permite pasar dos parámetros a la función de la derecha, mientras que '|>' especifica solo un parámetro ('Seq.zip' toma dos parámetros). –