首页 > 解决方案 > 如何在第一次出现字符串时拆分列?

问题描述

我有一个以下格式的数据框。我想拆分“。”之前的单词。在用户名列中并将其余部分保留为不同的列

+----+--------+
|Name|Username|
+----+--------+
| ABC|a.b.cdef|
+----+--------+

我想将用户名拆分为

+----+--------+---+------+
|Name|Username|  A|     B|
+----+--------+---+------+
| ABC|a.b.cdef|  a|b.cdef|
+----+--------+---+------+

前缀的长度(第一个之前.)不固定,因此我不能使用substring标准函数。

标签: apache-sparkapache-spark-sql

解决方案


对于这种特殊情况,我会(重新)考虑一个用户定义的函数(并避免使用正则表达式,因为几周后可能很难理解)。

val splitFirst = udf { (s: String) => s.split("\\.", 2) }

scala> data.withColumn("AB", splitFirst($"username")).show
+----+--------+-----------+
|Name|Username|         AB|
+----+--------+-----------+
| ABC|a.b.cdef|[a, b.cdef]|
+----+--------+-----------+

val solution = data
  .withColumn("AB", splitFirst($"username"))
  .withColumn("A", $"AB"(0))
  .withColumn("B", $"AB"(1))
scala> solution.show
+----+--------+-----------+---+------+
|Name|Username|         AB|  A|     B|
+----+--------+-----------+---+------+
| ABC|a.b.cdef|[a, b.cdef]|  a|b.cdef|
+----+--------+-----------+---+------+

诀窍是使用正确的String.split

public String[] split​(String regex, int limit)围绕给定正则表达式的匹配拆分此字符串。

limit 参数控制应用模式的次数,因此会影响结果数组的长度。

如果限制为正,则模式将最多应用限制 - 1 次,数组的长度将不大于限制,并且数组的最后一个条目将包含最后一个匹配分隔符之外的所有输入。


推荐阅读