如何从可选项列表中创建scala Map?

时间:2016-04-20 09:33:09

标签: scala

Scala从Option emelents列表中创建Map?

myMap = (0 to r.numRows - 1).map { i =>
  if (Option(r.getValue(i,"Name")).isDefined)
    (r.getValue(i, "Name")) -> (r.getValue(i, "isAvailable").toString)
}.toMap
foo(myMap) //here At this point, I'm geting the exception

我已经尝试了上面的代码,但没有编译:

Exception:
Error:(158, 23) Cannot prove that Any <:< (T, U).
                }.toMap
                  ^

1 个答案:

答案 0 :(得分:1)

也许试试这段代码:

val myMap = (0 until r.numRows) flatMap { i =>
  for {
    name <- Option(r.getValue(i, "Name"))
    available = r.getValue(i, "isAvailable").toString
  } yield (name, available)
}.toMap
foo(myMap)

您的问题很可能是在没有if的情况下使用else,而if是scala中的表达式,这意味着它会评估某些内容。

if (2 > 3) true

相当于

if (2 > 3) true else ()

所以类型是UnitBoolean的常见超类型Any,这就是你得到的错误。

请注意,您可以将to-1替换为untilOption执行相同的操作,但更具可读性。

您不应该使用isDefined真正检查map并对结果执行操作,如果这是真的,为此您使用for操作。

稍微解释一下我的实现:Option[(String, String)]部分将评估为"Name",如果存在None密钥则会包含您的元组,其他方式flatMap。从概念上讲,Option[(String, String)]将首先将您的索引范围更改为None的序列,然后展平它,即删除所有Some并展开所有"isAvailable"

如果你想检查for { name <- Option(r.getValue(i, "Name")) available <- Option(r.getValue(i, "isAvailable")) } yield (name, available.toString) 是否为空,你可以做类似的事情

const foo = c => {
    let rec = acc => x => x === undefined ? rec(acc + "o") : foo(acc + x);
    return c === undefined ? rec("o") : "f" + c;
};

foo('t'); // "ft"
foo()('t'); // "fot"
foo()()('t'); // "foot"