0

Having as Input a list of String (one of them could be None). How can I return a Array of String using Immutable Object.

It's pretty easy if I use var or Mutable Object, here an example:

def getArrayString(string: String, list1: List[String], list2: Option[List[String]]): Array[String] = {
  var ret = Array[String]()
  ret = ret :+ string
  if (list1.nonEmpty) {
    for (item <- list1) {
      ret = ret :+ item
    }
  }
  if (list2.isDefined) {
    for (item <- list2.get) {
      ret = ret :+ item
    }
  }
  ret
}

Question1: What if I want to use just val object?

N.B.: if list2 is None the returning array should not have any None Object

Question2: ..and if list1 and list2 were List[CustomClass] where CustomClass is

case class CustomClass(string:String)

How would you do?

Question3: ...What if we complicate the method with...

case class CustomClass1(string1:String)

case class CustomClass2(string2:String)

obviously CustomClass1 and CustomClass2 might have some other parameters in their class that make them different from each other. The signature of the method would be then:

def getArrayString( string: String
                , list1: List[CustomClass1]
                , list2: Option[List[CustomClass2]]
              ): Array[String]`
salvob
  • 1,300
  • 3
  • 21
  • 41

2 Answers2

1

You can use :: which will prepend an element to a list, and ++ which will concatenate 2 lists:

val ret = (string :: (list1 ++ list2.getOrElse(Nil))).toArray

For the updated version:

val ret = (string :: (list1 ++ list2.getOrElse(Nil)).map(_.string)).toArray
Alvaro Carrasco
  • 6,103
  • 16
  • 24
1

Every time I see Option I think "fold?".

def getArrayString( string: String
                  , list1: List[String]
                  , list2: Option[List[String]]
                  ): Array[String] =
  list2.foldLeft(string +: list1)(_++_).toArray

update (as requested)

case class CustomClass(string:String)
def getArrayString( string: String
                    , list1: List[CustomClass]
                    , list2: Option[List[CustomClass]]
                  ): Array[String] =
  string +: list2.foldLeft(list1)(_++_).map(_.string).toArray

Or the slightly more concise:

  Array(string) ++ (list1 /: list2)(_++_).map(_.string)
jwvh
  • 50,871
  • 7
  • 38
  • 64
  • Thank you jwvh, but this doesn't work if `list2` is `None` and it is less readable than Alvaro's answer – salvob Jan 10 '17 at 18:23
  • Really? What should be returned if `list2` is `None`? – jwvh Jan 10 '17 at 18:26
  • It has to return an Array of String.. EDIT: I did some testing and yes. Your code return what it should :) – salvob Jan 10 '17 at 18:33
  • I edited the question, could you extend your answer please? – salvob Jan 10 '17 at 18:44
  • Thank you, really appreciate it! ... but if `CustomClass` (say `CustomClass1` and `CustomClass2`, respectively for `list1` and `list2`) is not the same for both lists, this would not work though – salvob Jan 11 '17 at 10:13
  • `Array(string) ++ (list1.map(_.string) /: list2.map(_.map(_.string)))(_++_)` with this should work. But it is a little bit obscure to read... – salvob Jan 11 '17 at 10:53
  • @salvob, I don't quite understand your question and I don't see any situation where your rather verbose solution would hold any advantage over the more concise options I have posted. – jwvh Jan 11 '17 at 18:18
  • `case class CustomClass1(string:String)` `case class CustomClass2(string:String)` `def getArrayString( string: String , list1: List[CustomClass1] , list2: Option[List[CustomClass2]] ): Array[String]` – salvob Jan 12 '17 at 00:10
  • Ah, I see. Yes, your solution will work in that case, however I think I'd prefer it like this: `Array(string) ++ list1.map(_.string) ++ list2.getOrElse(Nil).map(_.string)`. But the _real_ solution is to pull the common attributes into a `trait`, then not only can you return to the simpler `getArrayString()` code I've proposed, it will also be able to process the inputs in either order: `List[Custom1], Option[List[Custom2]]` or vise versa. – jwvh Jan 12 '17 at 02:10