8

I have an array like this

(20140101,20140102,20140103,20140104,20140105,20140106,20140107,20140108)

I want to create a map from this by prefixing each value with "s3://" and concatenating three values with a comma.

Output:

val params = Map("1"-> "s3://20140101,s3://20140102,s3://20140103","2"-> "s3://20140104,s3://20140105,s3://20140106","3"->"s3://20140107,s3://20140108")

I'm a beginner and kindly request some thoughts here.

1
  • Are you saying you want a maximum of 3 s3 urls per map group? Commented Nov 19, 2014 at 18:07

4 Answers 4

12

This returns a Map[Int, Array[String]]. If you really want the values as a String, then use mapValues(_.mkString(",")) on the result.

scala> val xs = Array(20140101,20140102,20140103,20140104,20140105,20140106,20140107,20140108)          
xs: Array[Int] = Array(20140101, 20140102, 20140103, 20140104, 20140105, 20140106, 20140107, 20140108)

scala> xs.map(x => "s3://" + x).grouped(3).zipWithIndex.map(t => (t._2, t._1)).toMap
res16: scala.collection.immutable.Map[Int,Array[String]] = Map(0 -> Array(s3://20140101, s3://20140102, s3://20140103), 1 -> Array(s3://20140104, s3://20140105, s3://20140106), 2 -> Array(s3://20140107, s3://20140108))
Sign up to request clarification or add additional context in comments.

Comments

5

I think this will do what you want:

  val array = Array(20140101, 20140102, 20140103, 20140104, 20140105, 20140106, 20140107, 20140108)
  val result = array.
    sliding(3, 3). // this selects 3 elements at a time and steps 3 elements at a time
    zipWithIndex. // this adds an index to the 3 elements
    map({ case (arr, i) => (i + 1).toString -> arr.map(a => "s3://" + a.toString).mkString(",")}). // this makes a tuple and concats the array elements
    toMap // this transforms the Array of tuples into a map

  println(result) 
  //prints Map(1 -> s3://20140101,s3://20140102,s3://20140103, 2 -> s3://20140104,s3://20140105,s3://20140106, 3 -> s3://20140107,s3://20140108)

5 Comments

Great! I would put .view before all the operations so that new arrays won't be created every time
view is a strange beast, and it's implementation makes me not want to use it as it seems non-deterministic. With that said, I tried it and got this error Exception in thread "main" java.lang.ClassCastException: scala.collection.SeqViewLike$$anon$1 cannot be cast to scala.collection.mutable.IndexedSeqView
Oh that's actually strange.. Could you convert the array in the first line and try the operation?
Converting toList works, but doesn't that defeat the purpose of using the view?
I mean wrapping the array with scala.collection.mutable.WrappedArray. It only costs an instantiation, O(1). Just define val array as val array: IndexedSeq[Int]. It worked in my REPL :)
1

Just another variation, this time avoiding zipWithIndex and the key value swap

val xs = Array(20140101,20140102,20140103,20140104,20140105,20140106,20140107,20140108)

Iterator.from(0).zip{xs.grouped(3).map{"s://"+ _.mkString(",")}}.toMap

Comments

0

You can convert it to a tuple then turn that tuple into a map. Like this:

val xs = Array(20140101,20140102,20140103,20140104,20140105,20140106,20140107,20140108)

val xsMap = ((1 to (xs.length + 1))
    zip xs.map(valueAtIndex => "s://" + valueAtIndex)).toMap

This won't be particularly fast but it is simple and makes sense. Note: I only tested this will the new scala3 compiler: dotty. The scala version I am using is 3.0.1.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.