2012-05-14 11 views
5

¿Hay una manera de transformar sólo el primer elemento de una lista sin hacer algo súper hacky como:Transformar sólo el primer elemento de una lista Scala

val head = l1.head 
val tail = l1.tail 
val l2 = change(head) :: tail 

updated() parece que podría funcionar, pero no es una gran mejora:

val head = l1.head 
val l2 = l.update(0, change(head)) 

me gustaría algo así como:

val l2 = l1.updateHead(change(_)) 

¿hay ¿Cualquier cosa como eso?

+3

es 'val l2 = change (l1.head) :: l1.tail' really" super hacky "? – stew

+0

Quizás no, aunque todos sugirieron muchas alternativas que me parecieron más agradables. Creo que el enfoque de coincidencia de patrones de Robert es el más simple. – pr1001

Respuesta

15

se podría tratar de usar la coincidencia de patrones

val l2 = l1 match{ 
    case Nil => Nil 
    case x::xs => change(x)::xs 
} 

De esa manera usted no tiene que preocuparse si head realidad devuelve un elemento

+0

¡Patrón que combina rocas! Buena esa. –

8

Usted está haciendo su vida mucho más difícil por la introducción de variables en cada oportunidad. No lo hagas!

Tanto de las opciones que aparecen recogidos bastante limpio, si no se introducen variables temporales:

val l2 = change(l.head) :: l.tail 
val l2 = l.update(0, change(l.head)) 

tampoco es completamente seguro en las listas vacías, pero

val l2 = l.take(1).map(change) ::: l.drop(1) 

es.

También está siempre libre a la lista de enriquecer con su propio método, sin embargo:

class ReheadableList[A](xs: List[A]) { 
    def rehead[B >: A](f: A => B) = xs.take(1).map(f) ::: xs.drop(1) 
} 
implicit def lists_can_be_reheaded[A](xs: List[A]) = new ReheadableList(xs) 

(edit - cambiado para evitar errores con listas vacías). Ahora puede simplemente

val l2 = l.rehead(change) 
3

Probablemente haya MUCHAS maneras de hacerlo. A continuación se muestra una sesión de Scala REPL mostrando una versión

scala> val change = (x: Int) => x*2 
change: Int => Int = <function1> 

scala> val l = List(1,2,3) 
l: List[Int] = List(1, 2, 3) 

scala> l.headOption.map(x => change(x) :: l.drop(1)).getOrElse(Nil) 
res3: List[Int] = List(2, 2, 3) 
5

El uso de lentes parciales (described in this paper), se puede escribir algo como:

listHeadLens.set(list, newValue) 

donde listHeadLens se define como:

def listHeadLens[A] = new PartialLens[List[A], A] { 
    def apply: List[A] => Option[CoState[A, List[A]]] = { 
    case Nil => None 
    case x :: xs => Some(CoState(x, _ :: xs)) 
    } 
} 

I Creo que las lentes parciales llegarán a Scalaz 7. No estoy seguro.

1

Podrías hacerlo así.

val list = List("1","2","3") 
def change(str : String) = Some("x") 

val nlist = (list.headOption.flatMap(change(_)).toList ::: list.tail) 

en la consola.

scala> val list = List("1","2","3") 
list: List[java.lang.String] = List(1, 2, 3) 

scala> def change(str : String) = Some("x") 
change: (str: String)Some[java.lang.String] 

scala> val nlist = (list.headOption.flatMap(change(_)).toList ::: list.tail)   
nlist: List[java.lang.String] = List(x, 2, 3) 
Cuestiones relacionadas