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) 使用
::
而不是
:+
为性能预先添加元素。