Scala比较两个列表并构建字符串

时间:2018-04-20 09:59:22

标签: scala loops

我有两个列表如下:

InputColumns:

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

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)
)

我想要做的是在迭代它们之后生成一个字符串。因此,如果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
    }
})

2 个答案:

答案 0 :(得分: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 List[Option[String]]转换它们,其中每个子列表对应原始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)

如果您想将可选转换为类似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,,",  ...
// )

答案 1 :(得分:1)

只需使用输入数据中的每个地图映射标题。如果要插入一些不在地图中的值,请使用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)
但是,我不确定你想用这些字符串做什么。通常建议不惜一切代价避免使用串行化的序列化到字符串数据。