Scala 有效地从同一字符串中提取多个子字符串

Scala 有效地从同一字符串中提取多个子字符串,scala,Scala,我有一个包含键值对的URL字符串的大型数据集,我想从该字符串中捕获一个值列表。下面是字符串的一个示例: "GET /no_cache/bi_page?Log=1&pg_inst=600474500174606089&pg=mdot_fyc_pnt&platform=mdot&ver=10.c110&pid=157876860906745096&rid=157876731027276387&srch_id=-2&row=7&s

我有一个包含键值对的URL字符串的大型数据集,我想从该字符串中捕获一个值列表。下面是字符串的一个示例:

"GET /no_cache/bi_page?Log=1&pg_inst=600474500174606089&pg=mdot_fyc_pnt&platform=mdot&ver=10.c110&pid=157876860906745096&rid=157876731027276387&srch_id=-2&row=7&seq=1&tot=1&tsp=1&test_name=m_control&logDomain=http%3A%2F%2Fwww.xyz.com&ref_url=http%3A%2F%2Fm.xyz.com%2F&z=44134 HTTP/1.1"
所以如果我要返回的值列表来自键:pg,test\u name,some\u other\u key。。。我希望函数为此行返回mdot_fyc、m_control、NA

我可以写三行单独的正则表达式来捕捉每个值。但其中一些字符串很长,我可以提取几十个值,而不是三个


从同一字符串中提取多个值的最有效方法是什么?

这里是一个简单的单遍解决方案。让我知道它是否足够快

我不是URL方面的专家,所以它可能需要调整。基本上,它假定不存在未转义的空格“?”、“&”或“=”字符

可以使用低级opti对其进行进一步平滑

def extractParams(params: List[String], from: String): Map[String, String] = {
  val a = from.toCharArray
  val len = a.length

  import scala.annotation.tailrec
  @tailrec
  def extract(p: Set[String], start: Int, results: Map[String, String]): Map[String, String] = {
    var paramStart = start
    var nextEquals = -1
    var nextAmpersand = -1

    if (start == 0) {  // find start of params
      var i = 0
      while (i < len && a(i) != '?') {
        i += 1
      }
      if (i == len) return results
      paramStart = i
    }

    { // find equals
      var i = paramStart
      while (i < len && a(i) != '=') {
        i += 1
      }
      if (i == len) return results
      nextEquals = i
    }

    { // find nextAmpersand or end
      var i = nextEquals
      while (i < len && !(a(i) == '&' || a(i) == ' ')) {
        i += 1
      }
      nextAmpersand = i
    }
    val paramNameArr = new Array[Char](nextEquals - paramStart - 1)
    System.arraycopy(a, paramStart + 1, paramNameArr, 0, nextEquals - paramStart - 1)
    val paramName = new String(paramNameArr)
    var newResults = results
    var newP = p
    if (p.contains(paramName)) { // find param value
      val paramValueArr = new Array[Char](nextAmpersand - nextEquals - 1)
      System.arraycopy(a, nextEquals + 1, paramValueArr, 0, nextAmpersand - nextEquals - 1)
      val paramValue = new String(paramValueArr)
      newResults = newResults + (paramName -> paramValue)
      newP = p - (paramName)
    }
    if (nextAmpersand == len || a(nextAmpersand) == ' ') { // check for end
      return newResults
    } else {
      return extract(newP, nextAmpersand, newResults)
    }
  }
  extract(params.toSet, "GET ".length, Map.empty)
}

你需要使用正则表达式吗?你能使用像split这样的字符串操作方法吗?当你说大数据集是什么意思?几百?几千?数以百万计的?你是否已经尝试过一些东西,但发现效率太低了?根据预期的数据集,您可能不需要关心它的效率。这可能效率不高,但如果你只需要一组键,我会解析url并生成键/值对的映射,提取你感兴趣的键/值对。总的来说,我指的是数百万行。我尝试过使用split,但在我的示例上运行需要3倍的时间。我喜欢使用NET-A-PORTER进行URL解析,但我从未在数百万个URL上尝试过:在这种情况下,你会发现Aho–Corasick算法很有用。您可以从该页面找到Java实现。