2012-06-19 21 views
22

Estoy tratando de cortar una tupla, eliminando los dos últimos elementos. Intenté usar los métodos drop/take de la lista pero no puedo recuperar una tupla.Cómo rebanar una tupla en scala

Aquí está el enfoque Traté:

scala> val myTuple = (1, 2, 4, 5, 0, 5) 
myTuple: (Int, Int, Int, Int, Int, Int) = (1,2,4,5,0,5) 

scala> val myList = myTuple.productIterator.toList 
myList: List[Any] = List(1, 2, 4, 5, 0, 5) 

scala> val mySubList = myList.dropRight(2) 
mySubList: List[Any] = List(1, 2, 4, 5) 

scala> val mySubTuple = ??? 

vi here esa lista para tupla es (todavía?) Posible en Scala.

¿Hay otras maneras de obtener esa subtuple (sin tratar myTuple._1, myTuple._2 ...)?

+4

Creo que esto se puede hacer con [sin forma] (https://github.com/milessabin/shapeless) 'HList'. Eche un vistazo a [esta pregunta] (http://stackoverflow.com/questions/9028459/a-clean-way-to-combine-two-tuples-into-a-new-larger-tuple-in-scala). – incrop

Respuesta

38

Este es el tipo de cosa que shapeless puede hacer en una forma genérica , que implica la conversión en un HList.

Primero - get shapeless. Entonces plazo Scala con los tipos de método dependientes encendido (por defecto en 2.10):

C:\Scala\sdk\scala-2.9.2\bin>scala -Ydependent-method-types 
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_04). 
Type in expressions to have them evaluated. 
Type :help for more information. 

Añadir sin forma a la ruta de clase:

scala> :cp C:\Users\cmarsha\Downloads\shapeless_2.9.2-1.2.2.jar 
Added 'C:\Users\cmarsha\Downloads\shapeless_2.9.2-1.2.2.jar'. Your new classpath is: 
"C:\tibco\tibrv\8.2\lib\tibrvnative.jar;C:\Users\cmarsha\Downloads\shapeless_2.9.2-1.2.2.jar" 

Ahora vamos a jugar!

scala> (1, 2.3, 'a, 'b', "c", true) 
res0: (Int, Double, Symbol, Char, java.lang.String, Boolean) = (1,2.3,'a,b,c,true) 

Debemos importar sin forma

scala> import shapeless._; import Tuples._; import Nat._ 
import shapeless._ 
import Tuples._ 
import Nat._ 

Nos dirigimos nuestra tupla en una HList

scala> res0.hlisted 
res2: shapeless.::[Int,shapeless.::[Double,shapeless.::[Symbol,shapeless.::[Char,shapeless.::[java.lang.String,shapeless.::[Boolean,shapeless.HNil]]]]]] = 1 :: 2.3 :: 'a :: b :: c :: true :: HNil 

Luego tomamos el primer 4 (nótese que _4 es un parámetro de tipo, no es una argumento del método)

scala> res2.take[_4] 
res4: shapeless.::[Int,shapeless.::[Double,shapeless.::[Symbol,shapeless.::[Char, shapeless.HNil]]]] = 1 :: 2.3 :: 'a :: b :: HNil 

Ahora convertir de nuevo a una tupla

scala> res4.tupled 
res5: (Int, Double, Symbol, Char) = (1,2.3,'a,b) 

Podríamos acortar este:

val (a, b, c, d) = sixtuple.hlisted.take[_4].tupled 
//a, b, c and d would all have the correct inferred type 

Por supuesto, esto se generaliza a los primeros M elementos de una tupla N

+4

Asegúrese de incluir '-Ydependent-method-types' o obtendrá' no se pudo encontrar el valor implícito para el parámetro tupler: informe.Tupler [tomar .Out] '(me confundió por un tiempo tratando de encontrar una respuesta) –

+0

¡Respuesta impresionante, y por la tarde!(Zona horaria francesa :)) – iwalktheline

+0

¿Cómo cambió esto en 2.00 sin forma? No se puede obtener para compilar – Edmondo1984

5
scala> val myTuple = (1, 2, 4, 5, 0, 5) 
myTuple: (Int, Int, Int, Int, Int, Int) = (1,2,4,5,0,5) 

scala> myTuple match { 
    | case (a, b, c, d, _, _) => (a, b, c, d) 
    | } 
res0: (Int, Int, Int, Int) = (1,2,4,5) 
+0

Funciona, pero requiere escribir explícitamente la coincidencia de patrón. Estoy buscando una manera de hacerlo, sin importar la longitud de la tupla. – iwalktheline

+0

Ver mi respuesta - Tengo un ejemplo generalizado completamente trabajado usando la biblioteca informe de Miles Sabin –

3

¿qué tal:

 

scala> val myTuple = (1,2,4,5,0,5) 
myTuple: (Int, Int, Int, Int, Int, Int) = (1,2,4,5,0,5) 

scala> val (left,right):Tuple2[List[Int],List[Int]] = myTuple.productIterator.toList.splitAt(myTuple.productArity - 2) 
left: List[Int] = List(1, 2, 4, 5) 
right: List[Int] = List(0, 5) 

scala> val mytuple2 = (right(0),right(1)) 
mytuple2: (Int, Int) = (0,5) 


+0

genial :) No sabía que las tuplas son Product-s y tienen iterator y arity available –

Cuestiones relacionadas