基于列表元素索引的Scala映射列表

时间:2015-09-28 19:08:53

标签: scala apache-spark

我在Scala中创建了一个字符串列表,表示表中的列名:

val cols = List("Col1","Col2","Col3")

我想将其转换为以下字符串

(select Col1 as value,sum(1) as count from sometable group by Col1) a
union (select Col2 as value,sum(1) as count from sometable group by Col2)
union (select Col3 as value,sum(1) as count from sometable group by Col3)

目的是通过Spark SQL执行此字符串,以创建一个新的数据框,其中包含cols列表中列出的所有列的摘要(实际的SQL代码不仅包含sum(1)组件,而且与问题)。

我对Scala和一般编程都是全新的,并且发现这很棘手主要是因为在转换后的字符串中第一个“联合”之前需要的“a”(或者你选择的别名)。

所以我提出了以下解决方案(不要判断),有没有更好的方法呢?

def mapWithIndex (s : String, i : Int) {

var outputString = ""
if (i == 0) {outputString="(Select "+s+" as value, sum(1) as freq from sometable group by "+s+") a"}
else {outputString="(Select "+s+" as value, sum(1) as freq from sometable group by "+s+")"}
return outputString
}

val transformedString = cols.zipWithIndex.map(case (s,i) => mapWithIndex(s,i)).mkString(" union ")

代码中可能存在一些小错误,因为我不得不重新输入所有内容(我无法复制我正在工作的服务器),但我确信你会得到它的要点。 虽然这很好但感觉我因为以下原因而效率低下(可能还有很多):

  1. 看起来必须可以将所需的逻辑放入map()语句中的匿名(?)函数中。我找不到一种方法来访问List项目索引,该索引将显示字符串中是否应包含“a”字样。
  2. mapWithIndex函数包含一个var而不是val,从我读过的内容中我应该尽量避免使用
  3. 感觉mapWithIndex函数不应该在每个条件中重复整个select语句,而只是在i == 0时才附加“a”。我无法正确理解语法。
  4. 非常感谢您阅读我的问题,并提前感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:3)

val transformedString = cols
  .zipWithIndex
  .map {
    case (name, index) => s"(select $name as value,sum(1) as count from sometable group by $name)" + (if (index==0) " a" else "")
  }
  .mkString(" union ")

答案 1 :(得分:0)

def verify_token # This already works by using default values in the Android app code
  email = request.headers['HTTP_MY_APP_USER_EMAIL']
  token = request.headers['HTTP_MY_APP_USER_TOKEN']
  user = User.find_by_email(email)
  user && user.valid_token?(token) # returns true for default_user_token, for now
end