如何在Scala中将List[String]转换为Strings

huangapple go评论61阅读模式
英文:

How to convert List[String] to Strings in Scala

问题

我现在正在努力学习Scala。
我有一个映射,其中值是字符串列表 Map[String, List[String]],我想获取值并用逗号分隔以作为参数传递给一个函数。

我有以下代码:

def blah(myMap: Map[String, List[String]]) {
  var test = List() // 我试图创建一个新对象并附加到这个列表
  
  test ::= myMap.keys.foreach(key => new foo().withKey(key).withValues(myMap.get(key)))
}

我目前的问题在于 withValues 部分,因为我想要的不是值的数组,我只想要用逗号分隔的值,就像 withValue(value1, value2, ...) 一样。我该如何实现这一点?另外,我附加到列表的方式是否正确?
为了明确我的目标,我想让我的变量 test 类似于:

val test = List(new foo().withKey(key).withValues(value1, value2),
                new foo().withKey(key2).withValues(value3),
                new foon().withKey(key3).withValues(value4))

然而,因为我试图使这个通用化,我不知道函数将接收的键和值的数量,所以我尝试使用for循环。

英文:

I am struggling with Scala right now.
I have a map where the values is a list of strings Map[String, List[String]] I want to get value and separate with comma to pass as argument to a function.

I have the following

def blah (myMap: Map[String, List[String]]) {

var test = List() // I am trying to create a new object and append to this List
        
test ::= myMap.keys.foreach( key => new foo().withKey(key).withValues(myMap.get(key)))

}

My problem right now is in the withValues part because what I want is not array of values, I just want the values separated by comma like withValue(value1, value2, ...)
How can I accomplish that? Also is the way I am appending to the list correct?
Just to be clear what I am trying to do it's for my variable test to be something like

val test = List(new foo().withKey(key).withValues(value1, value2),
            new foo().withKey(key2).withValues(value3),
            new foon().withKey(key3).withValues(value4))

However, because I am trying to make this general where I don't know the number of keys and values the function will get, I am trying to use the for loop.

答案1

得分: 1

要实现withValue(value1, value2, ...),你可以定义你的函数如下:def withValues(values: String*),例如:

def withValues(values: String*): Unit = {
    values.foreach(println)
}

然后你可以调用这个函数:

scala> withValues("a")
a

scala> withValues("a", "b")
a
b

scala> val list = List("a", "b")
list: List[String] = List(a, b)

scala> withValues(list:_*)
a
b

但如果你想要传递列表中的所有元素,我认为更简单的方法是将withValues定义为def withValues(values: List[String]),然后Foo类和blah函数如下:

class Foo {
    def withKey(key: String): Foo = {
        // 做一些操作 ...
        println(key)
        this
    }

    def withValues(values: List[String]): Foo = {
        // 做一些操作 ...
        values.foreach(println)
        this
    }
}

def blah(myMap: Map[String, List[String]]): List[Foo] = {
    myMap.map { case(k,v) => new Foo().withKey(k).withValues(v) }.toList
}

调用blah函数:

scala> blah(Map("a" -> List("1"), "b" -> List("2", "3")))
a
1
b
2
3
res12: List[Foo] = List(Foo@636d4cdc, Foo@565b77ba)
英文:

For implementing withValue(value1, value2, ...):
you can define your function such as def withValues(values: String*), for example:

def withValues(values: String*): Unit = {
    values.foreach(println)
}

then you can invoke this function:

scala> withValues("a")
a

scala> withValues("a", "b")
a
b

scala> val list = List("a", "b")
list: List[String] = List(a, b)

scala> withValues(list:_*)
a
b

But if you want to pass the all elements in list, I think it is more simple that define withValues as def withValues(values: List[String]), then the class Foo and function blah looks like:

class Foo {
    def withKey(key: String): Foo = {
        // do something ...
        println(key)
        this
    }

    def withValues(values: List[String]): Foo = {
        // do something ...
        values.foreach(println)
        this
    }
}

def blah(myMap: Map[String, List[String]]): List[Foo] = {
    myMap.map { case(k,v) => new Foo().withKey(k).withValues(v) }.toList
}

invoke blah:

scala> blah(Map("a" -> List("1"), "b" -> List("2", "3")))
a
1
b
2
3
res12: List[Foo] = List(Foo@636d4cdc, Foo@565b77ba)

答案2

得分: 1

Variadic functions like:

def foo(strings: String*): Unit = ()

are intended to be called like

foo()
foo("value1")
foo("value1", "value2")
//...

However, these Type* are Seq[Type] underneath, so these lists of values are wrapped in Seq and then a single value is passed down.

If you already have a collection to pass there, you need it to be Seq, then the compiler won't complain when you do:

val list: List[String] = List("value")
foo(list.toSeq: _*) // : _* tells compiler it's a vararg
                    // instead of a single value to wrap in Seq

In Scala 3, as well as Scala 2.12/2.13 with -Xsource:3 flag set up in your build tool, you can use shorter syntax:

val list: List[String] = List("value")
foo(list.toSeq*)

If the type is already Seq you can skip .toSeq (while Lists, Vectors etc are subtypes of Seq, this particular interface often complains if you don't upcast collection to Seq).

Long story short, your code can be implemented as

// Scala 2 without -Xsource:3 flag
val test = myMap.map { case (key, values) =>
  new foo().withKey(key).withValues(values.toSeq: _*)
}.toList

// Scala 2.12/2.13 with -Xsource:3, Scala 3
val test = myMap.map { case (key, values) =>
  new foo().withKey(key).withValues(values.toSeq*)
}.toList
英文:

Variadic functions like:

def foo(strings: String*): Unit = ()

are intended to be called like

foo()
foo("value1")
foo("value1", "value2")
//...

However, these Type* are Seq[Type] underneath, so these lists of values are wrapped in Seq and then a single value is passed down.

If you already have a collection to pass there, you need it to be Seq, then the compiler won't complain when you do:

val list: List[String] = List("value")
foo(list.toSeq: _*) // : _* tells compiler it's a vararg
                    // instead of a s single value to wrap in Seq

In Scala 3, as well as Scala 2.12/2.13 with scalacOptions += "-Xsource:3" flag set up in your build tool, you can use shorter syntax:

val list: List[String] = List("value")
foo(list.toSeq*)

If the type is already Seq you can skip .toSeq (while Lists, Vectors etc are subtypes of Seq, this particular interface often complains if you don't upcast collection to Seq).

Long story short, your code can be implemented as

// Scala 2 without -Xsource:3 flag
val test = myMap.map { case (key, values) =>
  new foo().withKey(key).withValues(values.toSeq: _*)
}.toList

// Scala 2.12/2.13 with -Xsource:3, Scala 3
val test = myMap.map { case (key, values) =>
  new foo().withKey(key).withValues(values.toSeq*)
}.toList

huangapple
  • 本文由 发表于 2023年7月14日 08:20:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76683997.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定