2017-06-21 55 views
1

如何使用Scala的UDF改變串的次序如何在列更改字符串值的順序

root 
    |-- Loc: string (nullable = true) 
    +----------------+ 
    |    Loc| 
    +----------------+ 
    |8106f510000dc502| 
    +----------------+ 
8106f510000dc502 to 08f150000dc50261 

我想把它轉換成這樣的順序[3,1,5,7,6 ,(8-16),4,2]

+0

你可以添加更多的數據,例如? –

回答

2

出現就像一個Scala編碼任務,並且有差不多跟Spark沒有關係。

我會做到以下幾點:

// the dataset 
val loc = Seq("8106f510000dc502").toDF("Loc") 

// the udf for decoding loc 
def mydecode(codes: Seq[Int]) = udf { s: String => 
    codes.map(pos => s.charAt(pos)).mkString 
} 

val codes = Seq(3,1,5,7,6,4,2) 
val decoded = loc.withColumn("decoded", mydecode(codes)($"loc")) 
scala> decoded.show 
+----------------+-------+ 
|    Loc|decoded| 
+----------------+-------+ 
|8106f510000dc502|61501f0| 
+----------------+-------+ 

我要離開的範圍內codes陣列中,即(8-16)爲您的家庭運動。

0

如果你正在尋找從100z200轉向200z100在列Loc然後如下定義udf功能應該是足夠了(假設你在每一個字符串的中間在有z列)

def reverseReplace = udf((str: String) => { 
    val index = str.indexOf("z") 
    str.substring(index+1, str.length)+str.substring(index, index+1)+str.substring(0, index) 
}) 

可以調用udf功能

val m4=msc3.select("Loc").withColumn("Info", reverseReplace($"Loc")) 
m4.show(false) 

您將已經編輯

據我從您希望更新的問題理解輸出

+-------+-------+ 
|Loc |Info | 
+-------+-------+ 
|100z200|200z100| 
|30z400 |400z30 | 
|600z10 |10z600 | 
+-------+-------+ 

以下的最終結果爲[3,1,5,7,6,(8-16),4,2]訂單,以下可以是您的udf func灰

def reverseReplace = udf((str: String) => { 
    val len = str.length 
    val index = 16 > len match {case true => len case false => 16} 
    var finalStr = "" 
    if(len > 2) 
    finalStr += str.substring(3-1,3) 
    if(len > 0) 
    finalStr += str.substring(1-1,1) 
    if(len > 4) 
    finalStr += str.substring(5-1,5) 
    if(len > 6) 
    finalStr += str.substring(7-1,7) 
    if(len > 5) 
    finalStr += str.substring(6-1,6) 
    if(len > 7) 
    finalStr += str.substring(8-1, index) 
    if(len > 3) 
    finalStr += str.substring(4-1,4) 
    if(len > 1) 
    finalStr += str.substring(2-1,2) 
    if(finalStr == "") 
    finalStr = str 
    finalStr 
}) 

可以調用此udf功能如使用正則表達式和可分配一個分離器(在這種情況下「Z」)的UDF上述

+0

謝謝你的回答;但我想玩的字符順序不扭轉它。所以很抱歉我採取了不好的例子。例如'125fh569x到52fh55x69'把第三個字符放在第一位,等等....謝謝你的時間 –

+0

如果我對你的問題的編輯是正確的,並且如果將'125fh569x'轉爲'51h659xf2'然後看到我更新的答案。 :) –

0

另一種方法指出:

def flip(sep: String) = udf(
    (s: String) => { 
    val pattern = s"""(.*?)${sep}(.*)""".r 
    s match { 
     case pattern(a, b) => b + sep + a 
    } 
    } 
) 

val df = Seq(("100z200")).toDF("Loc") 

val dfFlipped = df.withColumn("Flipped", flip("z")($"Loc")) 

dfFlipped.show 
+-------+-------+ 
| Loc|Flipped| 
+-------+-------+ 
|100z200|200z100| 
+-------+-------+ 
+0

謝謝你的回答,但我試圖得到一個普通的udf當我可以玩所有的字符和混合的順序;像這個例子10ze864到ze81046 –