【问题标题】:Spark-Shell Scala XML how to concatenate attributesSpark-Shell Scala XML如何连接属性
【发布时间】:2015-12-09 20:37:49
【问题描述】:

我正在尝试用逗号分隔符连接 Scala 中的 XML 属性。

scala> val fileRead = sc.textFile("source_file")
fileRead: org.apache.spark.rdd.RDD[String] = source_file MapPartitionsRDD[8] at textFile at <console>:21

scala> val strLines = fileRead.map(x => x.toString)
strLines: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[9] at map at <console>:23

scala> val fltrLines = strLines.filter(_.contains("<record column1="))
fltrLines: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[10] at filter at <console>:25

scala> fltrLines.take(5)
res1: Array[String] = Array("<record column1="Hello" column2="there" column3="how" column4="are you?" />", "<record column1=...."

scala> val elem = fltrLines.map{ scala.xml.XML.loadString _ }
elem: org.apache.spark.rdd.RDD[scala.xml.Elem] = MapPartitionsRDD[34] at map at <console>:27

这是我需要用逗号连接column1,然后是column 2,然后是comma,然后column3的地方......事实上,我希望能够改变column3,column1,column2的顺序......也是。

scala> val attr = elem.map(_.attributes("column1"))
attr: org.apache.spark.rdd.RDD[Seq[scala.xml.Node]] = MapPartitionsRDD[35] at map at <console>:29

这是它现在的样子:

scala> attr.take(1)
res17: Array[String] = Array(Hello)

我需要这个:

scala> attr.take(1)
res17: Array[String] = Array(Hello, there, how, are you?)

或者这个,如果我喜欢的话:

scala> attr.take(1)
res17: Array[String] = Array(are you?, there, Hello)

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    这会做你想做的事。您可以获取属性列表并对其进行排序,但请注意,只有当您的 XML 记录具有所有相同的 column1, column2, 属性时,它才会起作用。

    scala> elem.map { r =>
       // get all attributes (columnN) and sort them  
       r.attributes.map {_.key}.toSeq.sorted.
         // get the values and convert from Node to String
         map { r.attributes(_).toString} // .toArray here if you want
                                         // Array here instead of List
              }.head
    res33: Array[String] = List(Hello, there, how, are you?)
    

    【讨论】:

    • 它在没有.head 的情况下工作。但我应该提到我不希望属性按顺序排列。其实我想通过列出属性来自己指定顺序。 val attr = elem.map(_.attributes("column7")) + elem.map(_.attributes("column2")) + elem.map(_.attributes("column11")) 之类的东西。
    • 我想通了,看看我的回答,感谢您的回复,它帮助我思考我做错了什么。
    【解决方案2】:

    所以这就是它对我的工作方式。我像以前一样将我的线路设置为scala.xml.Elem

    scala> val fileRead = sc.textFile("source_file")
    fileRead: org.apache.spark.rdd.RDD[String] = source_file MapPartitionsRDD[8] at textFile at <console>:21
    
    scala> val strLines = fileRead.map(x => x.toString)
    strLines: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[9] at map at <console>:23
    
    scala> val fltrLines = strLines.filter(_.contains("<record column1="))
    fltrLines: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[10] at filter at <console>:25
    
    scala> fltrLines.take(5)
    res1: Array[String] = Array("<record column1="Hello" column2="there" column3="how" column4="are you?" />", "<record column1=...."
    
    scala> val elem = fltrLines.map{ scala.xml.XML.loadString _ }
    elem: org.apache.spark.rdd.RDD[scala.xml.Elem] = MapPartitionsRDD[34] at map at <console>:27
    

    但是这次我没有使用attributes("AttributeName")方法,而是使用attributes.asAttrMap,它给了我一个Map[String,String] = Map(Key1 -&gt; Value1, Key2 -&gt; Value2, ....)类型:

    scala> val mappedElem = elem.map(_.attributes.asAttrMap)
    

    然后我指定了我自己的列顺序。这样,如果列或 XML 情况下的属性不存在,则数据将仅显示 null。我可以将null 更改为我想要的任何内容:

    val myVals = mappedElem.map { x => x.getOrElse("Column3", null) + ", " + x.getOrElse("Column1", null) }
    

    这就是我获得随机列顺序的方法,您可以在将 XML 文件转换为逗号分隔文件时将其称为更改列位置。

    当时的输出是:

    how, Hello
    

    【讨论】:

      猜你喜欢
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-08
      • 2014-04-25
      相关资源
      最近更新 更多