我想分割一个用逗号分隔的字符串,并将结果用作Seq
或Set
:
def splitByComma(commaDelimited: String): Array[String]
= commaDelimited.trim.split(',')
def splitByCommaAsSet(commaDelimited: String): Set[String]
= splitByComma(commaDelimited).toSet
def splitByCommaAsSeq(commaDelimited: String): Seq[String]
= splitByComma(commaDelimited).toSeq
val foods = "sushi,taco,burrito"
val foodSet = splitByCommaAsSet(foods)
// foodSet: scala.collection.immutable.Set[String] = Set(sushi, taco, burrito)
val foodSeq = splitByCommaAsSeq(foods)
// foodSeq: Seq[String] = List(sushi, taco, burrito)
但是,这是相当重复的。理想情况下,我希望有一个类似genericSplitByComma[Set](foods)
的东西,当我传入Set
时返回一个Set
,而当我传递Seq
时返回一个Seq
。
答案 0 :(得分:13)
@KrzysztofAtłasik的答案对 Scala 2.12
非常有用。
这是2.13
的解决方案。 (不确定是否是最好的方法)。
import scala.collection.Factory
import scala.language.higherKinds
def splitByComma[C[_]](commaDelimited: String)(implicit f: Factory[String, C[String]]): C[String] =
f.fromSpecific(commaDelimited.split(","))
// Or, as Dmytro stated, which I have to agree looks better.
commaDelimited.split(",").to(f)
您可以这样使用:
splitByComma[Array]("hello,world!")
// res: Array[String] = Array(hello, world!)
splitByComma[Set]("hello,world!")
// res: Set[String] = Set(hello, world!)
splitByComma[List]("hello,world!")
// res: List[String] = List(hello, world!)
答案 1 :(得分:11)
Scala中有一种名为to
的方法,只要作用域中有一个名为CanBuildFrom
的类型类,它就可以将任意集合转换为另一个。
import scala.collection.generic.CanBuildFrom
import scala.languageFeature.higherKinds
def genericSplitByComma[S[_]](s: String)(implicit cbf: CanBuildFrom[Nothing, String, S[String]]): S[String] = {
s.split(",").to[S]
}
genericSplitByComma[Set]("Hello, hello") //Set(Hello, hello)
genericSplitByComma[List]("Hello, hello") //List(Hello, hello)
genericSplitByComma[Array]("Hello, hello") //Array(hello, world!)
我们不需要约束S[_]
,因为如果范围内没有合适的CanBuildFrom
,则此函数不会编译。例如,这将失败:
genericSplitByComma[Option]("Hello, hello")
以下内容也会失败,因为我们的类型构造函数S[_]
仅接受一个类型参数,并且映射期望两个:
genericSplitByComma[Map]("Hello, hello")
正如Luis MiguelMejíaSuárez和Dmytro Mitin所注意到的那样,刚发布的Scala 2.13中的集合中有major refactor,因此它将适用于Scala 2.12。
答案 2 :(得分:6)
有一个简单的解决方法。并非完全符合要求的语法,但也很简洁,应该与2.13兼容。
def simpleSplitByComma(coll :Iterable[String]) =
coll.flatMap(_.trim.split(","))
simpleSplitByComma(Set("hello,world")) //res0: Set(hello, world)
simpleSplitByComma(Seq("bellow,world")) //res1: List(bellow, world)
simpleSplitByComma(Array("fellow,old")) //res2: ArrayBuffer(fellow, old)
simpleSplitByComma(Stream("end,of,the,world")) //res3: Stream(end, ?)