【问题标题】:Scala compare two lists and build stringScala比较两个列表并构建字符串
【发布时间】:2018-04-20 09:59:22
【问题描述】:

我有两个列表如下:

输入列:

List(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13)

输入数据:

List(
  Map(col2 -> dummy string, col7 -> 2016-01-01, col11 -> 2011-01-01),
  Map(col2 -> dummy string, col7 -> 2018-01-01, col11 -> 2018-01-01),
  Map(col2 -> dummy string, col7 -> 2018-04-01, col11 -> 2018-04-01),
  Map(col2 -> dummy string, col7 -> 2016-01-01, col11 -> 2016-01-01)
)

我想要做的是在我遍历它们之后生成一个字符串。因此,如果 colX 名称匹配,则在 Map 中给它值,否则给它 NULL 值。

所以在上面的示例中,我将循环 4 次,创建 4 个返回的字符串:

(Null, dummy string, Null, Null, Null, Null,2016-01-01, Null) ..etc..

我想如下开始。遍历我的输入列列表,然后遍历我的输入数据的每个键,但我觉得我还有很长的路要走。

inputColumns.foreach(column => {
    inputData.foreach{ case (k,v) =>
        // I get a constructor cannot be instantiated to expected type error
    }
})

【问题讨论】:

  • 变量col1, ..., col13中有什么?
  • 没什么,它们只是我的表格列的名称。我正在尝试构建一个 spark sql 查询,该查询将帮助我的插入指示值应放置在我要构建的字符串中的位置。

标签: scala loops


【解决方案1】:

在 Scala 中通常不鼓励使用null,这就是为什么我建议将此映射到List[Option[String]]。这将允许安全地从对转换后数据的函数调用中受益。

所以,假设你有这些初始值:

private val columns =
  List("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "col11", "col12", "col13")

private val input = List(
  Map("col2" -> "dummy string", "col7" -> "2016-01-01", "col11" -> "2011-01-01"),
  Map("col2" -> "dummy string", "col7" -> "2018-01-01", "col11" -> "2018-01-01"),
  Map("col2" -> "dummy string", "col7" -> "2018-04-01", "col11" -> "2018-04-01"),
  Map("col2" -> "dummy string", "col7" -> "2016-01-01", "col11" -> "2016-01-01")
)

我们可以将它们转换为List[Option[String]]List,其中每个子列表对应于原始Map

val rows = input.map(originalMap =>
  columns.map(column => originalMap.get(column))
)

每一行看起来像

List(None, Some(dummy string), None, None, None, None, Some(2016-01-01), None, None, None, Some(2011-01-01), None, None)

如果你还想使用空值:

val resultWithNulls = rows.map(row => row.map(_.getOrElse(null)))

给出如下行:

List(null, "dummy string", null, null, null, null, "2016-01-01", null, null, null, "2011-01-01", null, null)

如果你想将 optional 转换为类似 CSV 的字符串,它仍然很简单:

val resultAsCsvString = rows.map(row => row.map(_.getOrElse("")).mkString(","))
// List(
//  ",dummy string,,,,,2016-01-01,,,,2011-01-01,,",
//  ",dummy string,,,,,2018-01-01,,,,2018-01-01,,",  ...
// )

【讨论】:

    【解决方案2】:

    只需使用输入数据中的每个映射映射标题。如果您想插入一些地图中没有的值,请使用getOrElse。这段代码在这里:

    val col1 = "col1"
    val col2 = "col2"
    val col3 = "col3"
    val col4 = "col4"
    val col5 = "col5"
    val col6 = "col6"
    val col7 = "col7"
    val col8 = "col8"
    val col9 = "col9"
    val col10 = "col10"
    val col11 = "col11"
    val col12 = "col12"
    val col13 = "col13"
    
    val header = List(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13)
    
    val inputData = List(
      Map(col2 -> "dummy string", col7 -> "2016-01-01", col11 -> "2011-01-01"),
      Map(col2 -> "dummy string", col7 -> "2018-01-01", col11 -> "2018-01-01"),
      Map(col2 -> "dummy string", col7 -> "2018-04-01", col11 -> "2018-04-01"),
      Map(col2 -> "dummy string", col7 -> "2016-01-01", col11 -> "2016-01-01")
    )
    
    val rows = inputData.map { d =>
      header
        .map { h => d.getOrElse(h, "Null") }
        .mkString("(", ",", ")")
    }
    
    rows foreach println
    

    生成以下输出:

    (Null,dummy string,Null,Null,Null,Null,2016-01-01,Null,Null,Null,2011-01-01,Null,Null)
    (Null,dummy string,Null,Null,Null,Null,2018-01-01,Null,Null,Null,2018-01-01,Null,Null)
    (Null,dummy string,Null,Null,Null,Null,2018-04-01,Null,Null,Null,2018-04-01,Null,Null)
    (Null,dummy string,Null,Null,Null,Null,2016-01-01,Null,Null,Null,2016-01-01,Null,Null)
    

    不过,我不确定您想对这些字符串做什么。通常建议不惜一切代价避免使用字符串类型的序列化到字符串数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多