当前位置: 首页 > 知识库问答 >
问题:

如何提取以Scala中特定值开头的数组[字符串]的元素?

墨阳羽
2023-03-14

我有一个Scala数据框,它有以下模式:

filter_msg.printSchema()
root
|-- value: array (nullable = true)
|    |-- element: string (containsNull = true)

和数据样本:

|[SD:GK, 3.16.0, OS:Linux, (x86_64), AID:176]|

我想从这个数组字符串中提取值,其中元素以say SD开头并获取值,然后如果其操作系统获取值。问题是数组字符串中的位置不总是相同的,它不断变化,因此我无法使用

filter_msg.select($"value".getItem(1).as("SD"))

输出应为我提供一个数据帧:

Output=GK | Linux
Output.printSchema()
String,String

共有3个答案

王德华
2023-03-14

UDF可以用于:

val df = Seq(Array("SD:GK", "3.16.0", "OS:Linux", "(x86_64)", "AID:176")).toDF("value")

val extractArrayValues = (prefix: String, values: Seq[String]) =>
  values.filter(_.startsWith(prefix + ":")).map(_.split(":")(1)).headOption

val extractUDF = udf(extractArrayValues)
val result = df.select(
  extractUDF(lit("SD"), $"value").alias("SD"),
  extractUDF(lit("OS"), $"value").alias("OS")
)

结果是:

+---+-----+
|SD |OS   |
+---+-----+
|GK |Linux|
+---+-----+
田鸿彩
2023-03-14

下面是使用regex和regexp\u extract函数的另一种方法:

import org.apache.spark.sql.functions.{concat_ws, regexp_extract}

val df = Seq(
  Seq("SD:GK", "3.16.0", "OS:Linux", "(x86_64)", "AID:176")
).toDF

df.withColumn("to_str", concat_ws(",", $"value")) //concatenate array items into one string i.e: SD:GK,3.16.0,OS:Linux,(x86_64),AID:176
  .select(
    regexp_extract($"to_str", "SD:(\\w+),", 1) as "SD", //extract SD 
    regexp_extract($"to_str", "OS:(\\w+),", 1) as "OS"  //extract OS
  ).show(false)

// Output
// +---+-----+
// |SD |OS   |
// +---+-----+
// |GK |Linux|
// +---+-----+
苗信鸥
2023-03-14

您可以转换为rdd并提取如下值

// If you can conferm the data are always in same order
filter_msg.rdd.map(_.getAs[mutable.WrappedArray[String]](0))
  .map(row => {
    val sd = row(0).split(":").tail.head
    val os = row(2).split(":").tail.head
    (sd, os)
  } )
  .toDF("sd", "os")

或者您可以使用前面提到的@SleightX

filter_msg.rdd.map(_.getAs[mutable.WrappedArray[String]](0))
  .map(row => {
    val sd = row.filter(_.startsWith("SD:")).head.split(":").tail.head
    val os = row.filter(_.startsWith("OS:")).head.split(":").tail.head
    (sd, os)
  } )
  .toDF("sd", "os")

输出:

+---+-----+
|sd |os   |
+---+-----+
|GK |Linux|
+---+-----+
 类似资料:
  • 我得到以下字符串: 我想从里面拿走食物和饮料。 我尝试了以下代码: 但它给人的感觉是,食物很刺激,喝了很多,离食物很近,三个和四个。

  • 问题内容: 我有一个看起来像这样的数组: 我如何仅获取以其开头的元素? 问题答案:

  • 我有一个dataframe,格式如下 我希望在字符串之后获得数值,并创建一个新列。 org.apache.spark.sql.analysisException:由于数据类型不匹配,无法解析“split(,'value\:(\d+)”)“:参数1要求字符串类型,但是”“是数组类型。;;

  • 问题内容: 我有一个超过20,000行的文本文件,我需要从中提取特定行。该程序的输出完全是空白文件。 txt文件中有20,000行,该ISDN行不断重复很多时间,每个时间都有不同的值。我的文本文件包含以下数据。 问题答案: 我们假设您使用Java 7,因为这是2014年。 这是一种返回a的方法,其中每个元素都是一个ISDN:

  • 问题内容: 在CSS中,如何选择所有元素开头和结尾的元素? 例如,我想选择并应用以下样式: 问题答案: 以下CSS3选择器将完成此工作: 该表示什么应该开始。 该表示什么应该结束。 本身可以用另一个属性替换,例如,应用于时(例如):

  • 问题内容: 我正在尝试检查字符串是否以开头。我该如何检查? 问题答案: 使用 substr 函数返回字符串的一部分。 如果您要确保它不是另一个协议。我会改用https,因为https也可以匹配,例如http-protocol.com。 一般而言: