Scala: Как я могу использовать Fold * с картой? - PullRequest
11 голосов
/ 08 июля 2010

У меня есть Map [String, String], и я хочу объединить значения в одну строку.

Я вижу, как это сделать, используя List ...

scala> val l = List("te", "st", "ing", "123")
l: List[java.lang.String] = List(te, st, ing, 123)

scala> l.reduceLeft[String](_+_)
res8: String = testing123

Свернуть * или уменьшить *, кажется, правильный подход. Я просто не могу получить правильный синтаксис для карты.

Ответы [ 2 ]

32 голосов
/ 08 июля 2010

Складки на карте работают так же, как и в списке пар. Вы не можете использовать Reduce, потому что тогда тип результата должен быть таким же, как тип элемента (то есть пара), но вам нужна строка. Таким образом, вы используете foldLeft с пустой строкой в ​​качестве нейтрального элемента. Вы также не можете просто использовать _+_, потому что тогда вы попытаетесь добавить пару в строку. Вместо этого вы должны использовать функцию, которая добавляет накопленную строку, первое значение пары и второе значение пары. Итак, вы получите это:

scala> val m = Map("la" -> "la", "foo" -> "bar")                 
m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(la -> la, foo -> bar)

scala> m.foldLeft("")( (acc, kv) => acc + kv._1 + kv._2)
res14: java.lang.String = lalafoobar

Объяснение первого аргумента для сгиба:

Как вы знаете, функция (acc, kv) => acc + kv._1 + kv._2 получает два аргумента: второй - это пара ключ-значение, обрабатываемая в данный момент. Первый - это результат, накопленный до сих пор. Однако, каково значение acc, когда обрабатывается первая пара (а результат еще не накоплен)? При использовании reduce первое значение acc будет первой парой в списке (а первое значение kv будет второй парой в списке). Однако это не работает, если вы хотите, чтобы тип результата отличался от типов элементов. Поэтому вместо сокращения мы используем fold, где мы передаем первое значение acc в качестве первого аргумента foldLeft.

Вкратце: первый аргумент foldLeft говорит, каким должно быть начальное значение acc.

Как отметил Том, вы должны иметь в виду, что карты не обязательно поддерживают порядок вставки (Map2 и co. Do, но не hashmaps), поэтому строка может перечислять элементы в другом порядке, чем которые вы их вставили.

8 голосов
/ 08 июля 2010

На вопрос уже дан ответ, но я хотел бы отметить, что есть более простые способы создания этих строк, если это все, что вы хотите. Как это:

scala> val l = List("te", "st", "ing", "123")
l: List[java.lang.String] = List(te, st, ing, 123)

scala> l.mkString
res0: String = testing123

scala> val m = Map(1 -> "abc", 2 -> "def", 3 -> "ghi")
m: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,abc), (2,def), (3,ghi))

scala> m.values.mkString
res1: String = abcdefghi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...