代码之家  ›  专栏  ›  技术社区  ›  Andrei Koch

Scala:类型参数不符合trait Subtractable的类型参数界限

  •  2
  • Andrei Koch  · 技术社区  · 6 年前

    def group(string: String) = {
      val map = mutable.Map[Char, ListBuffer[Int]]()
      for (i <- string.indices) {
        val ch = string(i)
        if(map.contains(ch)) map(ch) += i
        else map += (ch -> ListBuffer(i))
      }
      map
    }
    

    当我试图编译时,出现了一个错误:

    错误:(14,30)类型参数[?,Iterable[Any]与PartialFunction[Int with Char,Any]与scala.collection.generic类.Subtractable[\u>:Int with Char<:AnyVal,Iterable[Any]with PartialFunction[Int with Char,Any]withscala.collection.generic类.Subtractable[\u>:Int with Char<:AnyVal,Iterable[Any]with PartialFunction[Int with Char,任何]与scala.collection.generic类.Subtractable[\ugt;:Int with Char<:AnyVal,Equals]]{def seq:Iterable[Any]with PartialFunction[Int with Char,Any]}]{def seq:Iterable[Any]with PartialFunction[Int with Char,Any]{def seq:Iterable[Any]with PartialFunction[Int with Char,Any]}}]不符合trait Subtractable的类型参数界限[A,+Repr<:scala.collection.generic类.可减[A,Repr]] val v=对于(i<-字符串索引) {

    似乎循环的值有问题。所以我在循环的最后一行添加了'true',现在一切正常:

    def group(string: String) = {
      val map = mutable.Map[Char, ListBuffer[Int]]()
      for (i <- string.indices) {
        val ch = string(i)
        if(map.contains(ch)) map(ch) += i
        else map += (ch -> ListBuffer(i))
        true
      }
      map
    }
    

    Scala版本:2.12.6

    3 回复  |  直到 6 年前
        1
  •  2
  •   Aleksey Isachenkov    6 年前

    正如你在书中看到的 https://docs.scala-lang.org/tutorials/FAQ/yield.html

    所以,你的 for

    for (i <- string.indices) {
      val ch = string(i)
      if(map.contains(ch)) map(ch) += i
      else map += (ch -> ListBuffer(i))
    }
    

    相当于

    string.indices.foreach(i => {
      val ch = string(i)
      if(map.contains(ch)) map(ch) += i
      else map += (ch -> ListBuffer(i))
    })
    

    foreach

    def foreach[U](f: A => U): Unit
    

    map(ch) += i ListBuffer ,但是 map += (ch -> ListBuffer(i)) Map . 当编译器试图识别 U 在里面 foreach公司 f: Int => U ,它在 列表缓冲区 地图

    你可以这样重写你的代码

    def group(string: String) = {
        val map = mutable.Map[Char, ListBuffer[Int]]()
    
        def update(i: Int): Unit = {
            val ch = string(i)
            if(map.contains(ch)) map(ch) += i
            else map += (ch -> ListBuffer(i))
        }
    
        for (i <- string.indices) update(i)
        map
    }
    

    但最好使用标准方法

    def group(string: String) = string.toCharArray.zipWithIndex.groupBy(_._1).mapValues(_.map(_._2))
    
        2
  •  2
  •   Yuval Itzchakov    6 年前

    方法不编译的原因是,返回的类型与 if-else 表情。一个回来了 ListBuffer[Int] Map[Char, ListBuffer[Int]] .

    def group(string: String): mutable.Map[Char, ListBuffer[Int]] = {
      val map = mutable.Map[Char, ListBuffer[Int]]()
      for (i <- string.indices) {
        val ch = string(i)
        if (map.contains(ch)) {
          map(ch) += i
          map
        } else map += (ch -> ListBuffer(i))
      }
      map
    }
    

    没有可变参数的附加方法 Map ListBuffer 可以是:

    def group(s: String): Map[Char, Int] = {
      s.split("\\W+")
       .flatten
       .zipWithIndex
       .groupBy { case (char, _) => char }
       .mapValues { arr => arr.map(_._2) }
    }
    
        3
  •  1
  •   lprakashv    6 年前

    def group(string: String): mutable.Map[Char, List[Int]] = {
    
        val map = mutable.Map.empty[Char, List[Int]]
    
        string.zipWithIndex.foreach { case (char: Char, index: Int) =>
            map += (char -> (index :: map.get(char).getOrElse(List())))
        }
    
        map
    }