以字符串检查为例了解集合和序列
Understanding Sets and Sequences using String checking as an example
我有一个字符串,我想交叉检查它是否完全由字母组成 space。
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz".toSet
if (str.forall(purestring(_))) println("PURE") else "NOTPURE"
上面的简明代码完成了这项工作。但是,如果我 运行 这样:
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet
str.forall(purealpha(_)) // CONCISE code
我得到一个错误(找到:Char ... 需要:Boolean)并且它只能以这种方式使用 contains 方法工作:
str.forall(purealpha.contains(_))
我的问题是如何在不将字符串转换为 Set 的情况下使用 CONCISE 形式。关于拥有我自己的 String class 以及正确的方法组合以启用漂亮代码的任何建议;或者可能是一些处理字符串的纯函数。
这只是我正在做的一个有趣的练习,所以我可以理解集合的各种方法(包括 apply 方法)的复杂细节以及如何编写漂亮简洁的代码和 classes。
如果我们查看源代码,我们会发现这两种实现都在做不同的事情,尽管给出的结果相同。
当您将其转换为 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
字面值与申请 Set 的结果不同。
关于更简洁的建议是在第二个示例中完全省略 (_)
(编译器类型推断会选择它):
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet
str.forall(purealpha.contains)
一种略有不同的方法是使用正则表达式模式。
val str = "my long string to test"
val purealpha = "[ a-z]+"
str matches purealpha // res0: Boolean = true
我有一个字符串,我想交叉检查它是否完全由字母组成 space。
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz".toSet
if (str.forall(purestring(_))) println("PURE") else "NOTPURE"
上面的简明代码完成了这项工作。但是,如果我 运行 这样:
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet
str.forall(purealpha(_)) // CONCISE code
我得到一个错误(找到:Char ... 需要:Boolean)并且它只能以这种方式使用 contains 方法工作:
str.forall(purealpha.contains(_))
我的问题是如何在不将字符串转换为 Set 的情况下使用 CONCISE 形式。关于拥有我自己的 String class 以及正确的方法组合以启用漂亮代码的任何建议;或者可能是一些处理字符串的纯函数。
这只是我正在做的一个有趣的练习,所以我可以理解集合的各种方法(包括 apply 方法)的复杂细节以及如何编写漂亮简洁的代码和 classes。
如果我们查看源代码,我们会发现这两种实现都在做不同的事情,尽管给出的结果相同。
当您将其转换为 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
字面值与申请 Set 的结果不同。
关于更简洁的建议是在第二个示例中完全省略 (_)
(编译器类型推断会选择它):
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet
str.forall(purealpha.contains)
一种略有不同的方法是使用正则表达式模式。
val str = "my long string to test"
val purealpha = "[ a-z]+"
str matches purealpha // res0: Boolean = true