2009-08-28 33 views
39

是否可以匹配Scala中的一系列值?一个范围可以在Scala中匹配吗?

例如:

val t = 5 
val m = t match { 
    0 until 10 => true 
    _ => false 
} 

m将是true如果t是0和10,但假之间否则。这一点当然不起作用,但有什么办法可以达到这样的效果吗?

+3

注意,通过写 “0至10” 你的意思是0,1,2,。 ..,9(含0,不含10)。如果你想包含10,使用“0到10”。 – Jesper 2009-08-28 11:11:02

+0

看到一个相关的stackoverflow的问题:[我如何模式匹配在Scala范围?](http://stackoverflow.com/questions/3160888/how-can-i-pattern-match-on-a-range-in -scala) – 2011-09-26 01:35:09

+0

标题询问如何将'Range'类型的值与几种可能性相匹配,例如“我有'(0..5)'还是'(1..6)'?” – Raphael 2011-09-26 18:33:51

回答

65

卫队使用Range

val m = t match { 
    case x if 0 until 10 contains x => true 
    case _ => false 
} 
+0

这很聪明!出于某种原因,我从来没有想过这样做... – 2009-08-28 14:12:24

27

您可以使用卫士:

val m = t match { 
    case x if (0 <= x && x < 10) => true 
    case _ => false 
} 
+0

就性能而言,此解决方案比@ alexander-azarov解决方案更好。有范围需要被初始化,然后是范围扫描。特别是对于大范围,这可能成为一个问题。 – Oosterman 2016-05-20 06:54:19

+1

'Range.contains'当然被覆盖,所以它不需要扫描任何东西!它仍然有一些额外的代码,但热点应该内联和优化它没有问题。 – 2016-05-20 08:33:53

2

这里有另一种使用范围来匹配:

val m = t match { 
    case x if ((0 to 10).contains(x)) => true 
    case _ => false 
} 
+0

这复制@Alexander阿扎罗夫的答案。 – Glenn 2015-02-12 15:14:14

+0

t == 10的错误匹配。 – 2016-09-23 16:58:11

2

有了这些定义:

trait Inspector[-C, -T] { 
    def contains(collection: C, value: T): Boolean 
    } 

    implicit def seqInspector[T, C <: SeqLike[Any, _]] = new Inspector[C, T]{ 
    override def contains(collection: C, value: T): Boolean = collection.contains(value) 
    } 

    implicit def setInspector[T, C <: Set[T]] = new Inspector[C, T] { 
    override def contains(collection: C, value: T): Boolean = collection.contains(value) 
    } 

    implicit class MemberOps[T](t: T) { 
    def in[C](coll: C)(implicit inspector: Inspector[C, T]) = 
     inspector.contains(coll, t) 
    } 

你可以做检查,像这样的:

2 in List(1, 2, 4)  // true 
2 in List("foo", 2)  // true 
2 in Set("foo", 2)  // true 
2 in Set(1, 3)   // false 
2 in Set("foo", "foo") // does not compile 
2 in List("foo", "foo") // false (contains on a list is not the same as contains on a set) 
2 in (0 to 10)   // true 

所以你需要将代码:

val m = x in (0 to 10) 
相关问题