2014-11-14 35 views
1

我有一个包含键值对的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_NAME”,“some_other_key” ......我会想函数返回( “mdot_fyc”,“m_control”,“NA”)。

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

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

+0

你需要使用正则表达式吗?你能用像split这样的字符串操作方法吗? – 2014-11-14 16:17:32

+1

当你说“大数据集”时,你是什么意思?数百?成千上万的?百万?你有没有尝试过一些东西,发现效率太低了?根据预期的数据集,您可能不需要关心它的有效性。这可能效率不高,但如果你只是想要一组键,我会解析url并生成一个key/value对的映射,提取你感兴趣的对。 – Daenyth 2014-11-14 17:05:51

+0

大到我的意思是数百万行。我曾尝试使用“拆分”,但它需要3倍的时间来运行我的示例。 – user1956609 2014-11-14 17:25:41

回答

0

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

我不是网址专家,所以可能需要调整。基本上它假设没有未转义的空格,'?','&'或'='字符。

它可以进一步与低级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) 
} 
相关问题