Reputation: 6548
I have a scala case class that is something like below.
case class Address(
city: Option[String] = None,
country: Option[String] = None
)
case class Student(
id: Option[String] = None,
name: Option[String] = None,
address: Option[Seq[Address]] = None,
phone: Option[Seq[String]] = None
)
Now I want to write a toCSV method for student that would generate a list of csv strings/lines for each student. I am unable to determine how to generate string format for fields that can have multiple values such as: address and phone.
For a student,
val student_1 = Student(
id = Some("1"),
name = Some("john"),
address = Some(Seq(
Address(Some("Newyork"),Some("USA")),
Address(Some("Berlin"),Some("Germany")),
Address(Some("Tokyo"),Some("Japan")),
)),
phone = Some(Seq(
"1111","9999","8888"
))
)
So, student_1.toCSV must result in following csv string:
id, name, address.city, address.country, phone
1 , John, Newyork , USA , 1111/9999/888
, , Berlin , Germany ,
, , Tokyo , Japan ,
This is the csv list of string where first string represents the first row and so on.I need to generate this list of strings for each student. Note that there could be multiple lines for each student because address and phones can have multiple values.In this case, there are 3 addresses and 2 phones for student John. How do I achieve this in scala ?
Addition:
So far, I am working to produce a List of csv lines i.e a list of Lists where each list would store one row. So, the list would look like below:
List(
List("id","name","address.city","address.country","phone"),
List("1" ,"John","Newyork" ,"USA" ,"11111/22222"),
List("" ,"" ,"Berlin" ,"Germany" ,""),
List("" ,"" ,"Tokyo" ,"Japan" ,"")
)
Upvotes: 1
Views: 387
Reputation: 6548
Based on the answer provided by @jwvh above,
I have come up with a solution which is working for me now:
val student_1 = Student(
id = Some("1"),
name = Some("john"),
address = Some(Seq(
Address(Some("Newyork"),Some("USA")),
Address(Some("Berlin"),Some("Germany")),
Address(Some("Tokyo"),Some("Japan"))
)),
phone = Some(Seq(
"1111","9999","8888"
))
)
def csvHeaders:List[String] = {
List("StudentId","Name","Address.City","Address.Province","Phones")
}
def toCSV:List[List[String]] ={
val maximumLength = address.getOrElse(Seq.empty[Address]).length max 1
//phone.getOrElse(Seq.empty[String]).length for earlier case where phones were kept in separate rows , done by @jwvh above
val idList = List.tabulate(maximumLength)(k => " ").updated(0,id.getOrElse(""))
val nameList = List.tabulate(maximumLength)(k => " ").updated(0,name.getOrElse(""))
val addressCityList = if(address.isDefined){
address.get.map{
k => k.city.getOrElse(" ")
}.toList.padTo(maximumLength," ")
} else{
List.tabulate(maximumLength)(k => " ")
}
val addressProvinceList = if(address.isDefined){
address.get.map{
k => k.province.getOrElse(" ")
}.toList.padTo(maximumLength," ")
} else{
List.tabulate(maximumLength)(k => " ")
}
val phoneList = if(phone.isDefined){
List.tabulate(maximumLength)(k => " ").updated(0,phone.get.padTo(maximumLength," ").mkString("/"))
} else{
List.tabulate(maximumLength)(k => " ")
}
val transposedList:List[List[String]] = List(idList,nameList,addressCityList,addressProvinceList,phoneList).transpose
transposedList.+:(csvHeaders)
}
So, now student_1.toCSV will return:
/* List(
List(StudentId, Name, Address.City, Address.Province, Phones),
List(1, john, Newyork, USA, 1111/9999/8888),
List( , , Berlin, Germany, ),
List( , , Tokyo, Japan, )
) */
Upvotes: 0
Reputation: 51271
In this I simplified your Address
type to just a String
, and I kept the phone
layout as you had it originally (i.e. the one I complained about in the comments). So this is more of a proof-of-concept rather than a finished product.
val student = Student(Some("1")
, Some("John")
, Some(Seq("Newyork", "Berlin", "Tokyo"))
, Some(Seq("1111","9999"))
)
student match {
case Student(i,n,a,p) =>
val maxLen = a.getOrElse(Seq("")).length max p.getOrElse(Seq("")).length
Seq( Seq(i.getOrElse("")).padTo(maxLen,"")
, Seq(n.getOrElse("")).padTo(maxLen,"")
, a.getOrElse(Seq()).padTo(maxLen,"")
, p.getOrElse(Seq()).padTo(maxLen,"")
).transpose
}
// res0: Seq[Seq[String]] = List( List(1, John, Newyork, 1111)
// , List(, , Berlin, 9999)
// , List(, , Tokyo, ))
Upvotes: 1