Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用模式匹配在“for”内过滤_Scala_Iterator_Pattern Matching - Fatal编程技术网

Scala 使用模式匹配在“for”内过滤

Scala 使用模式匹配在“for”内过滤,scala,iterator,pattern-matching,Scala,Iterator,Pattern Matching,我正在读取一个TSV文件,并使用如下内容: case class Entry(entryType: Int, value: Int) def filterEntries(): Iterator[Entry] = { for { line <- scala.io.Source.fromFile("filename").getLines() } yield new Entry(line.split("\t").map(x => x.toInt)) } case类条目(

我正在读取一个TSV文件,并使用如下内容:

case class Entry(entryType: Int, value: Int)

def filterEntries(): Iterator[Entry] = {
  for {
    line <- scala.io.Source.fromFile("filename").getLines()
  } yield new Entry(line.split("\t").map(x => x.toInt))
}
case类条目(entryType:Int,value:Int)
def filterEntries():迭代器[条目]={
为了{
第x.toInt行)
}
现在,我对过滤出
entryType
设置为0的条目感兴趣,并忽略列计数大于或小于2(与构造函数不匹配)的行。我想知道是否有一种惯用的方法来实现这一点,可能是在伴生对象中使用模式匹配和
方法。我唯一能想到的就是在生成的迭代器上使用
.filter


我也会接受不涉及
for
循环,但返回
迭代器[Entry]
的解决方案。这些解决方案必须能够容忍格式错误的输入。

您可以在循环的头部创建变量以供理解,然后使用保护:

编辑:确保数组的长度

for {
  line <- scala.io.Source.fromFile("filename").getLines()
  arr = line.split("\t").map(x => x.toInt)
  if arr.size == 2 && arr(0) != 0
} yield new Entry(arr(0), arr(1))
用于{
第x.toInt行)
如果arr.size==2&&arr(0)!=0
}新分录收益率(arr(0)、arr(1))

a
的左侧,我已使用以下代码解决它:

import scala.util.{Try, Success}

val lines = List(
  "1\t2",
  "1\t",
  "2",
  "hello",
  "1\t3"
)

case class Entry(val entryType: Int, val value: Int)
object Entry {
  def unapply(line: String) = {
    line.split("\t").map(x => Try(x.toInt)) match {
      case Array(Success(entryType: Int), Success(value: Int)) => Some(Entry(entryType, value))
      case _ =>
        println("Malformed line: " + line)
        None
    }
  }
}

for {
  line <- lines
  entryOption = Entry.unapply(line)
  if entryOption.isDefined
} yield entryOption.get
import scala.util.{Try,Success}
val行=列表(
“1\t2”,
“1\t”,
"2",
“你好”,
“1\t3”
)
案例类条目(val entryType:Int,val value:Int)
对象条目{
取消应用def(行:字符串)={
line.split(“\t”).map(x=>Try(x.toInt))匹配{
案例数组(Success(entryType:Int),Success(value:Int))=>Some(entryType,value))
案例=>
println(“格式错误的行:+行)
没有一个
}
}
}
为了{

行这是一种更先进的技术:

package object liner {
  implicit class R(val sc: StringContext) {
    object r {
      def unapplySeq(s: String): Option[Seq[String]] = sc.parts.mkString.r unapplySeq s
    }
  }
}

package liner {

  case class Entry(entryType: Int, value: Int)

  object I {
    def unapply(s: String): Option[Int] = util.Try(s.toInt).toOption
  }

  object Test extends App {
    def lines = List("1 2", "3", "", "  4  5  ", "junk", "0, 100000", "6 7 8")

    def entries = lines flatMap {
      case r"""\s*${I(i)}(\d+)\s+${I(j)}(\d+)\s*""" if i != 0 => Some(Entry(i, j))
      case __________________________________________________ => None
    }
    Console println entries
  }
}
希望正则表达式插值器很快就能进入标准发行版,但这表明它是多么容易装配。同样希望,scanf风格的插值器将允许使用
case f“$i%d”
轻松提取

我刚开始在模式中使用“拉长通配符”来对齐箭头

有一个蛹或幼虫regex宏:


是的,你是对的。可能是我写错了演示代码。不幸的是,输入文件可能包含不同数量的列,这些列与条目构造函数不匹配。当
entryType
不是0或者该行没有2个条目时,这将不会过滤,而是抛出一个
匹配错误=0,对吗?你没有单元测试,是吗。反问。(抱歉,只是开玩笑。不要阻止在这方面提供帮助。)哦,的确。这实际上是一个误读的规范(过滤掉!=检索):P但是
Array(type,value)
当然应该是
Array(entryType,value)
您应该发布您的解决方案作为您自己问题的答案。完成。无论如何,感谢您的支持。非常感谢:)这只是2.11版本,对吗?2.10 IIRC中的字符串插值器不匹配。很抱歉,但我真的不同意这是一个好主意:线性程序不进行编译时检查,它的参数字符串有意义(无子组强制执行等)。还要注意,
*
可能应该是
*?
,即使这样,你也会遇到这样的问题:你会捕捉到像“10 10 10”这样的句子。这可能不是OP想要的。@gzm0它是2.10犹太洁食。所以这是错误的::(我在hulu广告中看到这样的话是对的。)(更正了正则表达式并添加了3-int大小写。:)
package object liner {
  implicit class R(val sc: StringContext) {
    object r {
      def unapplySeq(s: String): Option[Seq[String]] = sc.parts.mkString.r unapplySeq s
    }
  }
}

package liner {

  case class Entry(entryType: Int, value: Int)

  object I {
    def unapply(s: String): Option[Int] = util.Try(s.toInt).toOption
  }

  object Test extends App {
    def lines = List("1 2", "3", "", "  4  5  ", "junk", "0, 100000", "6 7 8")

    def entries = lines flatMap {
      case r"""\s*${I(i)}(\d+)\s+${I(j)}(\d+)\s*""" if i != 0 => Some(Entry(i, j))
      case __________________________________________________ => None
    }
    Console println entries
  }
}