将元素列表转换为tuple5,防止索引超出范围

时间:2014-06-17 10:14:28

标签: scala scalding

我正在尝试从scala列表创建一个元组:

.map('path -> ('uri1, 'uri2, 'uri3, 'uri4, 'uri5)) {elems:List[String] =>

  (elems(0), elems(1), elems(2), elems(3), elems(4)) //ouf of bounds!
}

但是elems可能有1到5个元素,所以很明显我会命中一个超出范围的索引。

这样做的scala / scalding方法是什么?我猜测正确的方法是迭代1到5的范围并从那里生成元组。

当元素不存在时,我想返回null(出于兼容性原因)。

3 个答案:

答案 0 :(得分:5)

这里的方法实际上取决于您的要求。

如果您仅在Tuple5中定义了5个元素后才elem,那么简单模式匹配就是一种方法(当函数返回Option时,您可以展平在map之后获得预期结果):

  def convert(l: List[String]): Option[(String, String, String, String, String)] = l match {
    case e1 :: e2 :: e3 :: e4 :: e5 :: _ => Some((e1, e2, e3, e4, e5))
    case _ => None
  }

或者如果您在获取所有列表大小并将其转换为Tuple5后,您可以:

  • 使用如上所示的模式匹配并处理其余5个案例(列表中的0,1,2,3,4 elems)默认缺失值。

  • 使用scala.util.Try和默认(即elem(n)

  • 包裹您的Try(elem(1)).getOrElse("")来电
  • 将默认值添加到elem列表以填写缺失值

说明以下最后一个选项的示例:

  def convert(l: List[String], default : String): (String, String, String, String, String) = {
    val defaults = (1 to 5 - l.size).map(_ => default).toList
    l ++ defaults match {
      case e1 :: e2 :: e3 :: e4 :: e5 :: _ => (e1, e2, e3, e4, e5)
    }
  }

答案 1 :(得分:1)

有一种方法可以在一行中执行此操作,stringListList[String]default为默认

new Tuple(stringList.map(_.asInstanceOf[AnyRef]): _*) ++ (stringList.size until 5).map(_ => default)

问题在于它不是类型安全的,所以我给了Norbert一个upvote,因为他的回答是 - 而且可能更容易阅读。

答案 2 :(得分:1)

您可以根据需要使用空值填充列表:

.map('path -> ('uri1, 'uri2, 'uri3, 'uri4, 'uri5)) {elems:List[String] =>
  val padded= elems ++ List.fill(5)(null)
  (padded(0), padded(1), padded(2), padded(3), padded(4))  //No ouf of bounds!
}