以字符串检查为例了解集合和序列

时间:2017-05-27 20:18:32

标签: scala scala-collections

我有一个字符串,我想交叉检查它是否完全由字母和空格组成。

 val str = "my long string to test"
 val purealpha = " abcdefghijklmnopqrstuvwxyz".toSet

 if (str.forall(purestring(_))) println("PURE") else "NOTPURE"

上面的CONCISE代码完成了这项工作。但是,如果我这样运行:

 val str = "my long string to test"
 val purealpha = " abcdefghijklmnopqrstuvwxyz"   // not converted toSet

 str.forall(purealpha(_))    // CONCISE code

我收到一个错误(找到:Char ... required:Boolean),它只能通过这种方式使用contains方法:

str.forall(purealpha.contains(_))

我的问题是如何在不将字符串转换为Set的情况下使用CONCISE表单。有关使用正确的方法组合创建自己的String类以启用漂亮代码的任何建议;或者也许是一些处理字符串的纯函数。

这只是我正在做的一个有趣的练习,所以我可以理解集合上各种方法的复杂细节(包括应用方法)以及如何编写简洁的代码和类。

2 个答案:

答案 0 :(得分:1)

如果我们查看源代码,我们可以看到这两个实现都在做不同的事情,尽管给出了相同的结果。 当您将其转换为Set并使用forAll时,您最终会为该集合调用apply方法。以下是在代码中显式调用apply的方法,也使用匿名函数中的命名参数:

if (str.forall(s => purestring.apply(s))) println("PURE") else "NOTPURE" // first example
str.forall(s => purealpha.apply(s)) // second example

无论如何,让我们来看看申请Set的源代码(来自GenSetLike.scala):

/** Tests if some element is contained in this set.
   *
   *  This method is equivalent to `contains`. It allows sets to be interpreted as predicates.
   *  @param elem the element to test for membership.
   *  @return  `true` if `elem` is contained in this set, `false` otherwise.
   */
  def apply(elem: A): Boolean = this contains elem

当您离开String字面值时,您必须专门调用.contains(这是从SeqLike.scala获取的源代码):

/** Tests whether this $coll contains a given value as an element.
   *  $mayNotTerminateInf
   *
   *  @param elem  the element to test.
   *  @return     `true` if this $coll has an element that is equal (as
   *              determined by `==`) to `elem`, `false` otherwise.
   */
  def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem)

您可以想象,申请String字面值不会产生与申请集合相同的结果。

关于更简洁的建议是在第二个示例中完全省略(_)(编译器类型推断会选择它):

val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz"   // not converted toSet
str.forall(purealpha.contains)

答案 1 :(得分:1)

稍微不同的方法是使用正则表达式模式。

val str = "my long string to test"
val purealpha = "[ a-z]+"
str matches purealpha   // res0: Boolean = true