我有一个字符串,我想交叉检查它是否完全由字母和空格组成。
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类以启用漂亮代码的任何建议;或者也许是一些处理字符串的纯函数。
这只是我正在做的一个有趣的练习,所以我可以理解集合上各种方法的复杂细节(包括应用方法)以及如何编写简洁的代码和类。
答案 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