String 用不在嵌套函数调用内的逗号拆分字符串
我想按参数拆分函数参数列表 参数可以是函数调用,如:String 用不在嵌套函数调用内的逗号拆分字符串,string,scala,for-comprehension,String,Scala,For Comprehension,我想按参数拆分函数参数列表 参数可以是函数调用,如: foo(...) 或任何字符序列。例如: "fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg" 我想得到: List("first_arg", "some_foo(arg1, foo2(arg1, arg2, foo3())", "third_arg") 我实现它如下(): 在通过参数ListExpression进行迭代后,我们必须附加最后一个参数
foo(...)
或任何字符序列。例如:
"fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg"
我想得到:
List("first_arg", "some_foo(arg1, foo2(arg1, arg2, foo3())", "third_arg")
我实现它如下():
在通过参数ListExpression
进行迭代后,我们必须附加最后一个参数
我们可以用更实用的方式重构它吗?也许foldLeft会有帮助……?事实上,foldLeft是一种可能性。它帮助我们删除可变变量(我们在Scala中尽量避免): 返回
List("fisrt_arg", "some_foo(arg1, foo2(arg1, arg2, foo3())", "arg3"))
foldLeft
将遍历一个序列(在我们的例子中是一个List[Char]
),分别处理每个Char以填充一个“累加器”(要返回的List[String])
注意初始化
(字符串:+',')
,它允许我们将最后一次拆分也包括在拆分列表中。否则,在foldLeft的末尾,我们将在累加器元组的第二项(List[Char])中进行最后一次拆分,而不是将其包含在第一项(List[String])。实际上,foldLeft是一种可能。它帮助我们删除可变变量(我们在Scala中尽量避免):
返回
List("fisrt_arg", "some_foo(arg1, foo2(arg1, arg2, foo3())", "arg3"))
foldLeft
将遍历一个序列(在我们的例子中是一个List[Char]
),分别处理每个Char以填充一个“累加器”(要返回的List[String])
注意初始化
(字符串:+',')
,它允许我们将最后一次拆分也包括在拆分列表中。否则,在foldLeft的末尾,我们将在累加器元组的第二项(List[Char])中进行最后一次拆分,而不是将其包含在第一项(List[String])。我的想法与另一个答案基本相同,只是在“word”级别进行操作。我不知道我是否喜欢用这种方式修改列表的最后一个元素——携带“当前拆分”的想法将是另一种选择
val result = string
.split(",")
.foldLeft((0, List[String]())) {
case ((0, l), term) =>
(term.count(_ == '(') - term.count(_ == ')'), (term :: l))
case ((openCount, l), term) =>
val finalElt = l.head
(
openCount + term.count(_ == '(') - term.count(_ == ')'),
List(finalElt, term).mkString(",") :: l.tail)
}
._2
.reverse
我的想法与另一个答案基本相同,只是在“单词”层面上操作。我不知道我是否喜欢用这种方式修改列表的最后一个元素——携带“当前拆分”的想法将是另一种选择
val result = string
.split(",")
.foldLeft((0, List[String]())) {
case ((0, l), term) =>
(term.count(_ == '(') - term.count(_ == ')'), (term :: l))
case ((openCount, l), term) =>
val finalElt = l.head
(
openCount + term.count(_ == '(') - term.count(_ == ')'),
List(finalElt, term).mkString(",") :: l.tail)
}
._2
.reverse
递归是神圣的。请参阅-不是单个变量:
val s = "fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg"
def tokenize (argumentlist: String): List[String] = {
def tokenize (arglist: List[Char], sofar: String, inList: Int): List[String] = arglist match {
case Nil => List (sofar)
case '(' :: tail => tokenize (tail, sofar + '(', inList + 1)
case ')' :: tail => tokenize (tail, sofar + ')', inList - 1)
case ',' :: tail => if (inList > 0) {
tokenize (tail, sofar + ',', inList)
} else {
sofar :: tokenize (tail, "", inList)
}
case c :: tail => tokenize (tail, sofar + c, inList)
}
tokenize (argumentlist.toList, "", 0)
}
tokenize (s)
inList计算我们在列表中的深度
如果我们不只是传递sofar字符串,而是传递到目前为止的列表,我们可以使其尾部递归,但它不会让人觉得它可能会深入到以函数为参数的函数中,以函数为参数
陷阱:
val s = "\"stringliteral w. (misleading brace\", f(a, b(c, d, e()), f), g"
您可能希望在最后应用一些修剪:
scala> val res = tokenize (s)
res: List[String] = List(fisrt_arg, " some_foo(arg1, foo2(arg1, arg2, foo3()), arg3)", " third_arg")
scala> res.mkString ("<", "><", ">")
res372: String = <fisrt_arg>< some_foo(arg1, foo2(arg1, arg2, foo3()), arg3)>< third_arg>
scala>val res=tokenize
res:List[String]=List(first_arg,“some_foo(arg1,foo2(arg1,arg2,foo3()),arg3)”,“third_arg”)
scala>res.mkString(“”)
res372:String=
递归是神圣的。请参阅-不是单个变量:
val s = "fisrt_arg, some_foo(arg1, foo2(arg1, arg2, foo3()), arg3), third_arg"
def tokenize (argumentlist: String): List[String] = {
def tokenize (arglist: List[Char], sofar: String, inList: Int): List[String] = arglist match {
case Nil => List (sofar)
case '(' :: tail => tokenize (tail, sofar + '(', inList + 1)
case ')' :: tail => tokenize (tail, sofar + ')', inList - 1)
case ',' :: tail => if (inList > 0) {
tokenize (tail, sofar + ',', inList)
} else {
sofar :: tokenize (tail, "", inList)
}
case c :: tail => tokenize (tail, sofar + c, inList)
}
tokenize (argumentlist.toList, "", 0)
}
tokenize (s)
inList计算我们在列表中的深度
如果我们不只是传递sofar字符串,而是传递到目前为止的列表,我们可以使其尾部递归,但它不会让人觉得它可能会深入到以函数为参数的函数中,以函数为参数
陷阱:
val s = "\"stringliteral w. (misleading brace\", f(a, b(c, d, e()), f), g"
您可能希望在最后应用一些修剪:
scala> val res = tokenize (s)
res: List[String] = List(fisrt_arg, " some_foo(arg1, foo2(arg1, arg2, foo3()), arg3)", " third_arg")
scala> res.mkString ("<", "><", ">")
res372: String = <fisrt_arg>< some_foo(arg1, foo2(arg1, arg2, foo3()), arg3)>< third_arg>
scala>val res=tokenize
res:List[String]=List(first_arg,“some_foo(arg1,foo2(arg1,arg2,foo3()),arg3)”,“third_arg”)
scala>res.mkString(“”)
res372:String=
您完全可以将for
替换为foldLeft
,因此可以使用val
而不是var
。将累加器变量设置为(functionInvokationCounter、previousArgumentPositions、arguments)
。不过,关于子字符串,我有另一个想法。@hoyland你能告诉我这个想法吗?我的想法是,不要按字符进行拆分,而是先拆分,
,然后根据需要合并结果列表的元素。不过,还没算出来。@hoyland听起来很有趣。实际上我已经考虑过了,但我决定走另一条路。它的实现看起来很复杂。您完全可以用foldLeft
替换for
,因此可以使用val
而不是var
。将累加器变量设置为(functionInvokationCounter、previousArgumentPositions、arguments)
。不过,关于子字符串,我有另一个想法。@hoyland你能告诉我这个想法吗?我的想法是,不要按字符进行拆分,而是先拆分,
,然后根据需要合并结果列表的元素。不过,还没算出来。@hoyland听起来很有趣。实际上我已经考虑过了,但我决定走另一条路。它的实现看起来很复杂,看起来有点像Java的收集器。无论如何,它看起来更漂亮。看起来有点像Java的收集器。不管怎么说,它看起来漂亮多了。不错,从没想过这样做。我冒昧地提出了一个编辑:1)。\u 2从返回的元组中提取列表[String]。2) 使用::
而不是:+
为性能预先添加元素。很好的一种方法,从未想过这样做。我冒昧地提出了一个编辑:1)。\u 2从返回的元组中提取列表[String]。2) 使用::
而不是:+
为性能预先添加元素。