Scala 如何使方法返回与输入相同的泛型?

Scala 如何使方法返回与输入相同的泛型?,scala,generics,type-conversion,polymorphism,scala-collections,Scala,Generics,Type Conversion,Polymorphism,Scala Collections,我想拆分一个由逗号分隔的字符串,并将结果用作Seq或Set: def splitByComma(commaDelimited: String): Array[String] = commaDelimited.trim.split(',') def splitByCommaAsSet(commaDelimited: String): Set[String] = splitByComma(commaDelimited).toSet def splitByCommaAsSeq(commaD

我想拆分一个由逗号分隔的字符串,并将结果用作
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
,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[\u]
,因为如果范围中没有合适的
CanBuildFrom
,该函数将无法编译。例如,这将失败:

genericSplitByComma[Option]("Hello, hello")
下面的操作也会失败,因为我们的类型构造函数
S[\u]
只接受一个类型参数,映射需要两个:

genericSplitByComma[Map]("Hello, hello")

正如路易斯·米格尔·梅西亚·苏亚雷斯(Luis Miguel Mejía Suárez)和德米特罗·米廷(Dmytro Mitin)所注意到的,在刚刚发布的Scala 2.13中,集合中有很多,因此它将适用于Scala 2.12。@KrzysztofAtłasik的答案对于Scala
2.12

这是针对
2.13
的解决方案。(不完全确定这是否是最好的方法)

您可以这样使用:

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!)

有一个简单的解决方法。不完全是请求的语法,但同样简洁,应该与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, ?)

commaDelimited.split(“,”)至(f)
。快乐2.13!我也很好奇。def splitByComma[C](s:String)(隐式f:Factory[String,C]):C=s.split(“,”).to(f)@DmytroMitin哦,这就是
到[List]
到(List)
的变化,因为它现在接收到一个工厂,每个伴生对象现在都是一个工厂,我终于得到了它:DNow我们必须等待,看看yhylord把绿色复选框放在哪里!我真的很喜欢这个,可能会用到类似的东西,但我觉得我必须接受另一个完全符合我要求的答案:)
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, ?)