Reputation: 18347
I'm trying to create a tuple from a scala list:
.map('path -> ('uri1, 'uri2, 'uri3, 'uri4, 'uri5)) {elems:List[String] =>
(elems(0), elems(1), elems(2), elems(3), elems(4)) //ouf of bounds!
}
But the elems
may have between 1 and 5 elements, so obviously I will hit an index out of bounds exception.
What's the scala/scalding way of doing this? I'm guessing that the proper way is to iterate a range from 1 to 5 and generate the tuple from there.
I'd like to return null
(for compatibility reasons) when the elements do not exist.
Upvotes: 0
Views: 789
Reputation: 3749
You can pad the list with nulls as necessary:
.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!
}
Upvotes: 1
Reputation: 31533
There is a way to do this in 1 line, let stringList
be the List[String]
and default
be some default
new Tuple(stringList.map(_.asInstanceOf[AnyRef]): _*) ++ (stringList.size until 5).map(_ => default)
Problem with this is it's not typesafe, so I gave Norbert an upvote because his answer is - and perhaps easier to read.
Upvotes: 1
Reputation: 2618
The approach here really depends on your requirements.
If you're after Tuple5
only when there are 5 elements defined in elem
then a simple pattern match is a way to go (and as the function returns Option
you can flatten it after map to get an expected result):
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
}
Alternatively if you're after taking all the list sizes and converting them to Tuple5 with some default you can:
Use pattern matching as shown above and handle the remaining 5 cases (0,1,2,3,4 elems in the list) defaulting missing values.
Wrap your elem(n)
calls with scala.util.Try and default (i.e. Try(elem(1)).getOrElse("")
)
Add the default values to the elem
list to fill in the missing values
Example illustrating last option below:
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)
}
}
Upvotes: 5