Conseguir un conjunto de tipos de una unión discriminado de diferentes tipos de matrices en C #

StackOverflow https://stackoverflow.com/questions/1939113

  •  20-09-2019
  •  | 
  •  

Pregunta

Si tengo una unión discriminado de diferentes tipos de matrices cómo puedo convertir a sus tipos 'reales'?

type ItemStuff = 
   | Colors of string[]
   | Sizes of int[]

let foo = Sizes [|1;2;3|]

Después de ejecutar el anterior cuando consigo el valor de foo veo:

val foo : ItemStuff = Sizes [|1;2;3|]

¿Cómo puedo obtener una matriz real de la int de foo? ¿Estoy perdiendo una sintaxis que me permite el acceso a algo así como foo.[2]? No puedo enumerar a través de foo así que no era capaz de usar el mapa. Podría escribir un miembro de ItemStuff que devuelve una matriz adecuadamente escrito para cada tipo diferente de la matriz que voy a volver, pero que simplemente no parece correcto?

¿Cuáles son mis mejores enfoques aquí?

Esto es lo que terminé haciendo. alguna idea sobre mejores formas de hacerlo?

type ItemProp =
| Colors of string[]
| Sizes of int[]
| Quants of int[]
member this.GetColors() =
   match this with
   | Colors (stringArray) ->
       stringArray
   | _ -> null
member this.GetIntArr() =
   match this with
   | Sizes (intArray) | Quants (intArray) ->
       intArray
   |_ -> null

foo.GetIntArr()
¿Fue útil?

Solución

  

¿Cómo puedo obtener una matriz real de la int de foo?

Ese es el problema real, ya que se acaba de foo dice que tiene el tipo ItemStuff. Por lo tanto, no tiene por qué contienen una Sizes valor en absoluto -. Podría ser un Colors así

Por lo tanto el proyecto implica decidir aquí

let getIntArray = function
    | Sizes arr -> arr
    | Colors _  -> failwith "Given value doesn't contain an int array`

getIntArray foo trabajará correctamente, pero getIntArray (Colors [||]) fallará, pero de un tipo a nivel tanto son válidas.

Tenga en cuenta que si estás completamente seguro de que la operación se realizará correctamente, puede utilizar el patrón de coincidencia directa:

let getIntArray (Sizes arr) = arr

Otros consejos

Por lo general tendrá que utilizar la coincidencia de patrones, ya que no se sabe si un ItemStuff tiene colores o tamaños. Si definitivamente sabe que usted tiene una instancia Sizes, se puede hacer algo como:

let (Sizes arr) = foo

para tirar de la matriz de vuelta.

Si no son en realidad lo que representa un bien / o escenario (colores o tamaños), considerar el uso de un tipo de registro aquí:

type ItemStuff = 
    { Colors : string[];
      Sizes : int[] } with
    static member Default = { Colors = [||]; Sizes = [||] }

let foo = { ItemStuff.Default with Sizes = [|1;2;3|] }
printfn "%A" foo.Colors    // [||]
printfn "%A" foo.Sizes     // [|1; 2; 3|]
printfn "%d" foo.Sizes.[2] // 3

También puede devolver un tipo de opción con la opción Ninguno si la unión discriminado no era un Sizes.

let getIntArray item =
    match item with
    | Sizes(i) -> Some(i)
    | _        -> None

Pero hay que tener en cuenta que al final de F # una función siempre transforma un tipo de datos de entrada en un tipo de datos de salida, o una función sólo tiene un efecto secundario (imprimir algo en la pantalla o insertar datos en una matriz).

Así, por ejemplo, si sólo desea imprimir el Sizes (o nada si es un Colors) será más corto para escribir una nueva función para ese propósito:

let printSizes item =
    match item with
    | Sizes(i) -> printfn "%A" i
    | _        -> ()

en lugar de:

let getIntArray item =
    match item with
    | Sizes(i) -> Some(i)
    | _        -> None

let res = getIntArray foo

(function | Some(i) -> printfn "%A" i | _ -> ()) res
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top