Scala:当两个项目之一满足某些条件时进行模式匹配 [英] Scala: Pattern matching when one of two items meets some condition

查看:55
本文介绍了Scala:当两个项目之一满足某些条件时进行模式匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常编写代码来比较两个对象,并根据它们是否相同或不同以及它们的不同来产生一个值.

I'm often writing code that compares two objects and produces a value based on whether they are the same, or different, based on how they are different.

所以我可能会写:

val result = (v1,v2) match {
  case (Some(value1), Some(value2)) => "a"
  case (Some(value), None)) => "b"
  case (None, Some(value)) => "b"
  case _ = > "c"
}

第 2 种和第 3 种情况确实相同,所以我尝试编写:

Those 2nd and 3rd cases are the same really, so I tried writing:

val result = (v1,v2) match {
  case (Some(value1), Some(value2)) => "a"
  case (Some(value), None)) || (None, Some(value)) => "b"
  case _ = > "c"
}

但没有运气.

我在几个地方遇到过这个问题,这只是一个具体的例子,更一般的模式是我有两件事,我想知道是否只有其中一个满足某个谓词,所以我会喜欢写这样的东西:

I encounter this problem in a few places, and this is just a specific example, the more general pattern is I have two things, and I want to know if one and only one of them meet some predicate, so I'd like to write something like this:

val result = (v1,v2) match {
  case (Some(value1), Some(value2)) => "a"
  case OneAndOnlyOne(value, v: Option[Foo] => v.isDefined ) => "b"
  case _ = > "c"
}

所以这里的想法是 OneAndOnlyOne 可以配置一个谓词(在本例中为 isDefined),并且您可以在多个地方使用它.

So the idea here is that OneAndOnlyOne can be configured with a predicated (isDefined in this case) and you can use it in multiple places.

以上根本不起作用,因为它向后,谓词需要传递到提取器而不返回.

The above doesn't work at all, since its backwards, the predicate needs to be passed into the extractor not returned.

这样的事情怎么样?

val result = (v1,v2) match {
  case (Some(value1), Some(value2)) => "a"
  case new OneAndOnlyOne(v: Option[Foo] => v.isDefined )(value) => "b"
  case _ = > "c"
}

与:

class OneAndOnlyOne[T](predicate: T => Boolean) {
  def unapply( pair: Pair[T,T] ): Option[T] = {
    val (item1,item2) = pair
    val v1 = predicate(item1)
    val v2 = predicate(item2)

    if ( v1 != v2 )
      Some( if ( v1 ) item1 else item2 )
    else
      None
  }
}

但是,这不会编译.

谁能看到使此解决方案起作用的方法?或者提出另一种解决方案?我可能使这比它更复杂:)

Can anyone see a way to make this solution work? Or propose another solution? I'm probably making this more complicated than it is :)

推荐答案

如果您必须支持任意谓词,您可以从中派生(基于 丹尼尔的想法):

If you have to support arbitrary predicates you can derive from this (which is based on Daniel's idea):

List(v1, v2) filter (_ %2 == 0) match {
    case List(value1, value2) => "a"
    case List(value) => "b"
    case _ => "c"
}

函数定义:

def filteredMatch[T,R](values : T*)(f : T => Boolean)(p: PartialFunction[List[T], R]) : R = 
    p(List((values filter f) :_* ))

现在你可以这样使用它:

Now you can use it like this:

filteredMatch(v1,v2)(_ %2 == 0){
    case List(value1, value2) => "a"
    case List(value) => "b"
    case _ => "c"
}

我不太确定这是否是一个好主意(即可读).但仍然是一个很好的练习.

I'm not so sure if it's a good idea (i.e. readable). But a neat exercise nonetheless.

如果能匹配元组就好了:case (value1, value2) =>... 而不是列表.

It would be nice if you could match on tuples: case (value1, value2) => ... instead of lists.

这篇关于Scala:当两个项目之一满足某些条件时进行模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆