2009-06-01 14 views
6

Soy nuevo en f #Calculando el producto cartesiano de una lista de números con F #

estoy trato de calcular los productos cartesianos de una lista de números. Yo "tomé prestado" esto.

let xs = [1..99] 
let ys = [1..99] 
seq {for x in xs do for y in ys do yield x * y} 

¿Hay alguna manera mejor o más elegante?

Gary

+0

Pregunta relacionada aquí: http://stackoverflow.com/questions/482866/f-cross-product-of-two-lists – Benjol

Respuesta

9

Otra possibiltiy para abordar el problema sobre la base de la funcionalidad proporcionada por el módulo lista sería:

let xs = [1..99] 
let ys = [1..99] 
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y)) 

que evite las llamadas adicionales a .concat y también debe hacer el trabajo.

Pero me quedaré con su solución. Debería ser el más legible y el verdadero gancho. (Solo intente leer los códigos en voz alta. El suyo es perfectamente comprensible y los Noldorins o los míos no).

+1

¡Ah, me preguntaba dónde fue el método 'mapconcat'! Parece que se acaba de renombrar a 'recoger' en la versión más nueva. – Noldorin

+0

Con respecto a cuán comprensible/legible de cada una de nuestras soluciones es, creo que esto es algo subjetivo. Ciertamente hemos proporcionado soluciones de estilo más "funcionales", mientras que OP sugirió una solución (perfectamente buena) que utiliza construcciones "imperativas" típicamente. Sospecho que alguien de una base funcional podría encontrar cualquiera de nuestros métodos más claros. – Noldorin

2

En efecto, existe una forma un poco más elegante (al menos en el sentido funcional) para calcular los productos cartesianos, que utiliza las funciones que existen dentro de la clase List. (No hay necesidad de involucrar a secuencias o bucles aquí, al menos no directamente.)

Prueba esto:

let xs = [1..99] 
let ys = [1..99] 
xs |> List.map(fun x -> ys |> List.map(fun y -> x * y)) |> List.concat 

Ligeramente más largo es cierto, aunque más funcional en el estilo, parecería.

+1

En realidad, el código en la pregunta está más cerca de una lista de comprensión que su código, en mi opinión . La tuya es más como la versión desacralizada de una lista de comprensión. –

+0

Sí, no me refería a las listas de comprensión en realidad, no estoy seguro de que haya un nombre especial para eso, pero me refería a las funciones de Lista. *. – Noldorin

+0

¿Puede explicar lo que quiere decir con "no hay necesidad de involucrar secuencias", no entiendo cuáles son los beneficios de usar List.map sobre Seq.map? – ninegrid

7

Descargo de responsabilidad: No tengo una máquina con el F # actual instalado, así que no puedo probar mi código. Básicamente, sin embargo, si usted roba sequence de Haskell, se puede escribir el programa como

let cartesian = sequence >> List.map product 

y ejecutarlo como

cartesian [[1..99]; [1..99]] 

se explica cómo escribir sequence aquí. Es una versión generalizada de la expresión de secuencia que escribiste. Solo maneja un número ilimitado de listas: { for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }.

let rec sequence = function 
    | [] -> Seq.singleton [] 
    | (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) } 
// also you'll need product to do the multiplication 
let product = Seq.fold_left1 (*) 

Entonces se puede escribir el programa como

let cartesian xs ys = [xs; ys] |> sequence |> List.map product 
// ... or one-argument, point-free style: 
let cartesian' = sequence >> Seq.map product 

Es posible que tenga que cambiar algunos Seq s a List s.

Sin embargo, la cantidad de personas que pueden adivinar el significado de su lista de comprensión no general es probablemente mucho mayor que la que reconocerá el nombre sequence, por lo que probablemente esté mejor con la lista comprendida. sequence es útil en cualquier momento que desee ejecutar una lista completa de expresiones de cálculo.

+0

+1 para invocar mónadas –

+0

Notarás que evité decir "mónada". Sin embargo, la "expresión de cálculo" todavía no es tan amigable como "algo cálido y difuso". :) –

Cuestiones relacionadas