【问题标题】:Transform only the first element of a Scala list仅转换 Scala 列表的第一个元素
【发布时间】:2012-05-22 05:28:28
【问题描述】:

有没有办法只转换列表的第一个元素而不做一些超级 hacky 之类的事情:

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

updated() 看起来可以工作,但改进不大:

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

我喜欢这样的东西:

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

有类似的吗?

【问题讨论】:

  • val l2 = change(l1.head) :: l1.tail 真的是“超级黑客”吗?
  • 也许不是,尽管每个人都建议了很多对我来说看起来更好的替代方案。我认为罗伯特的模式匹配方法是最简单的。

标签: list scala map


【解决方案1】:

你可以尝试使用模式匹配

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

这样你就不用担心head是否真的返回一个元素

【讨论】:

  • 模式匹配岩石!不错。
【解决方案2】:

你会在每一个机会中引入变量,让你的生活变得更加艰难。不要这样做!

如果不引入临时变量,您列出的两个选项都相当干净:

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

在空列表上都不是完全安全的,但是

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

是。

您也可以随时使用自己的方法来丰富列表,但是:

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)

(编辑--更改以避免空列表错误)。现在你可以

val l2 = l.rehead(change)

【讨论】:

    【解决方案3】:

    使用部分镜头 (described in this paper),您可以编写如下内容:

    listHeadLens.set(list, newValue)
    

    其中listHeadLens 定义为:

    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))
      }
    }
    

    我认为部分镜头将进入 Scalaz 7。不过我不确定。

    【讨论】:

      【解决方案4】:

      可能有很多方法可以做到这一点。下面是一个显示一个版本的 Scala REPL 会话

      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】:

        你可以这样做。

        val list = List("1","2","3")
        def change(str : String ) = Some("x")
        
        val nlist = (list.headOption.flatMap(change(_)).toList ::: list.tail)
        

        在控制台中。

        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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多