我有一个集合,我希望将另一个变量与其任何一个元素相匹配。我知道我可以这样手动执行此操作:
fruits = Set("a", "b", "c", "d")
toMatch = ("a", "fruit")
toMatch match {
case (("a" | "b" | "c" | "d", irrelevant)) => true
}
但是有没有办法在比赛声明中使用水果,所以我不必手动扩展它
编辑:我目前正在使用if条件来执行此操作,我想知道是否有一些语法糖我可以用它来内联fruits = Set("a", "b", "c", "d")
toMatch = ("a", "fruit")
toMatch match {
case ((label, irrelevant)) if fruits.contains(label) => true
}
如果没有其他答案,我会将第一个回复的人标记为解决方案!抱歉,那里缺乏清晰度。
EDIT2:如果你想知道的原因是
fruits = Set("a", "b", "c", "d")
vegetables = Set("d", "e", "f")
toMatch = ("a", "fruit")
toMatch match {
case ((label, "fruit")) if fruits.contains(label) => true
case ((label, "vegetable")) if vegetables.contains(label) => true
}
我想结合这两种情况,因此我对每种返回类型都有一个条件
答案 0 :(得分:1)
您可以使用匹配
中的'if'语句来执行此操作 val fruits = Set("a", "b", "c", "d")
val toMatch = ("a", "otherVar")
toMatch match {
case (fruit, _) if fruits.contains(fruit) => true
}
答案 1 :(得分:1)
如果您只需要这两种情况,那么使用'如果'或@Eugene答案就足够了,但对于更多情况我会使用Map:
val fruits = Set("a", "b", "c", "d")
val vegetables = Set("d", "e", "f")
val meats = Set("q", "w")
val food = Map("fruits" -> fruits, "vegetables" -> vegetables, "meats" -> meats)
val toMatch = ("a", "fruit")
scala> food(toMatch._2)(toMatch._1)
res3: Boolean = true
答案 2 :(得分:1)
你可以编写一个自定义提取器来获得你想要的语法糖:
object FruitAndVegetable {
val fruits = Set("a", "b", "c", "d")
val vegetables = Set("d", "e", "f")
def main(args: Array[String]): Unit = {
List(
"a" -> "fruit",
"a" -> "vegetable",
"d" -> "fruit",
"d" -> "vegetable",
"e" -> "fruit",
"f" -> "vegetable"
) foreach {
toMatch =>
val result = toMatch match {
case CustomExtractor(`fruits`, "fruit") => "found a fruit"
case CustomExtractor(`vegetables`, "vegetable") => "veggy"
case _ => "Neither fruit nor veggy"
}
println(result)
}
}
object CustomExtractor {
def unapply(toMatch: (String, String)): Option[(Set[String], String)] =
if ((fruits contains toMatch._1) && toMatch._2 == "fruit") Some(fruits -> toMatch._2)
else if (vegetables contains toMatch._1) Some(vegetables -> toMatch._2)
else None
}
}
但请注意,这种方法存在三个问题(可能更多我无法想到的):
CustomExtractor
依赖于fruits
和vegetables
集合,以及"fruit"
。原因:我们想从Set[String]
中提取String
(因为我们与集合匹配),因此我们需要找到一个包含字符串的集合,即fruits
和{{ 1}}。由于集合不是不同的,我们还需要知道在vegetables
包含在两个集合中的情况下返回哪个集合(此处:toMatch._1
)。在这种情况下,我们需要查看"d"
。
toMatch._2
仍然需要实施"不公平"匹配(虽然你可以比我做的更优雅)
CustomExtractor
- 陈述受到污染"通过对象标识符case
(或任何你想要的名称)如果您有很多CustomExtractor
- 与这些值匹配的语句,我只会考虑这个解决方案。在这种情况下,您只需要编写一次提取器并可以重复使用它。
PS :我对提取器不是很熟悉,所以也许你可以想出一个更好的方法来解决这个问题,使用提取器。
答案 3 :(得分:0)
这是您可以使用的另一种自定义unapply方法,它更安全。
object CustomExtractor {
case class Group(label: String, values: Set[String])
}
class CustomExtractor {
private[this] val labelMap = mutable.HashMap[String, CustomExtractor.Group]()
def newMatcher(label: String, values: String*): CustomExtractor.Group = {
if (labelMap.contains(label)) {
throw new IllegalArgumentException(s"Label Already Mapped: ${labelMap(label)}")
}
labelMap.getOrElseUpdate(label, new CustomExtractor.Group(label, Set(values: _*)))
}
def unapply(toMatch: (String, String)): Option[CustomExtractor.Group] = {
val (value, label) = toMatch
labelMap.get(label).filter(_.values.contains(value))
}
}
val extractor = new CustomExtractor
val fruits = extractor.newMatcher("fruit", "a", "b", "c", "d")
val vegetables = extractor.newMatcher("vegetable", "d", "e", "f")
val tests = List("a" -> "fruit", "a" -> "vegetable", "d" -> "fruit", "d" -> "vegetable", "e" -> "fruit", "f" -> "vegetable")
for (test <- tests) {
test match {
case extractor(`fruits`) => println(s"$test is definitely a fruit.")
case extractor(group) => println(s"$test was matched to ${group.label}.")
case _ => println(s"$test was not matched!")
}
}