2009-08-28 14 views
39

Ist es möglich, eine Reihe von Werten in Scala abzustimmen?Kann ein Bereich in Scala verglichen werden?

Zum Beispiel:

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

m wäre true wenn t zwischen 0 war und 10, aber ansonsten false. Dieses kleine Stück funktioniert natürlich nicht, aber gibt es einen Weg, etwas Ähnliches zu erreichen?

+3

Beachten Sie, dass "0 bis 10" Sie bedeuten, 0, 1, 2, durch das Schreiben. .., 9 (einschließlich 0, ohne 10). Wenn Sie 10 hinzufügen möchten, verwenden Sie "0 bis 10". – Jesper

+0

Siehe eine verwandte stackoverflow-Frage: [Wie kann ich eine Musterübereinstimmung in einem Bereich in Scala finden?] (Http://stackoverflow.com/questions/3160888/how-can-i-pattern-match-on-a-range-in-) -scala) –

+0

Der Titel fragt, wie man einen Wert des Typs 'Range' mit verschiedenen Möglichkeiten, z "Habe ich' (0..5) 'oder' (1..6) '?" – Raphael

Antwort

65

Wache mit Range:

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

Das ist sehr schlau! Aus irgendeinem Grund habe ich nie daran gedacht, es so zu machen ... –

27

Sie verwenden Wachen:

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

In Bezug auf die Leistung ist diese Lösung besser als @ Alexander-Azarov-Lösung. Dort muss der Bereich initialisiert werden, gefolgt von einem Bereichsscan. Gerade bei großen Reichweiten kann dies zum Problem werden. – Oosterman

+1

'Range.contains' wird natürlich überschrieben, so dass nichts gescannt werden muss! Es ist immer noch ein wenig zusätzlichen Code, aber Hotspot sollte es ohne Probleme inline und optimieren. –

2

Hier ist eine andere Art und Weise mit einem Bereich entsprechen:

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

Dies dupliziert @Alexander Azarovs Antwort. – Glenn

+0

Falsche Übereinstimmung für t == 10. –

2

Mit diesen Definitionen:

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

Sie können Kontrollen wie diese tun:

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 

So ist der Code, den Sie würde müssen:

val m = x in (0 to 10) 
Verwandte Themen