LINUX.ORG.RU

Красиво смерджить список Map, с заполнением плейсхолдером отсутствующих значений

 , ,


0

2

У меня есть список Map, вида:

Map[String, List[String]]

Мне надо его смерджить, но не просто смерджить, а заполнять пустыми строками(либо другим плейсхолдером) ключи, которые отсутствуют.

Грубо говоря, если :

    List(Map("one" -> List("1"), "two" -> List("2")),
         Map("one" -> List("11"), "two" -> List("22"), "three" -> List("3")), 
         Map("four" -> List("44")))

То на выходе я хочу получить что-то типа такого.

    Map(
          "one"   -> List("1", "11", ""),
          "two"   -> List("2", "22", ""), 
          "three" -> List("", "3", ""), 
          "four"  -> List("", "", "44")
       )

То, что я сделал - крайне убого выглядит.

Я насовал там кучу изменяемых сущностей, сложил все ключи и просто итерировался - вышло громоздко и не понятно.

Может у кого есть желание и немного времени, чтобы научить меня делать такие вещи красиво? В идеале - в Scala стиле, но без сторонних либ, типа Catz и т.д

Заранее Вам спасибо!

Ответ на: комментарий от maxcom

Добавить туда элемент просто или слить два списка в один Например:

List(
Map("one" -> List("1", "11"), "two" -> List("2")),
Map("one" -> List("20")),
Map("two" -> List("19", "22"))
)

То будет:

Map(
          "one"   -> List("1", "11", "20", ""),
          "two"   -> List("2", "", "19", "22"), 
   )

Т.е сначала из первой Map берется 1, 11 из второй 20, в третьей ключ one отсутствует и ставится пропуск. Аналогично с two: из первой берется 2, во второй отсутствует и ставится пропуск, из третьей берется 19 и 22.

Принцип такой

aarexer ()
Ответ на: комментарий от aarexer
val src = List(Map("one" -> List("1"), "two" -> List("2")),
  Map("one" -> List("11"), "two" -> List("22"), "three" -> List("3")),
  Map("four" -> List("44")))

val keys = src.map(_.keySet).fold(Set.empty)(_ ++ _)

keys.toSeq.map(key ⇒  key -> src.flatMap(_.getOrElse(key, List("")))).toMap

так? хотя тоже не красиво

maxcom ★★★★★ ()
Ответ на: комментарий от aarexer

Ты же изначально плейсхолдеры вводил, чтобы иметь обратную операцию к мерджу? Типа чтобы всегда можно было восстановить, в каком именно мапе отсутствовал ключ. Иначе я не понимаю смысл такого мерджа.

Map( «one» -> List(«1», «11», «20», ""), «two» -> List(«2», "", «19», «22»), )

Ну так вот, если да, то в этом месте ты потерял обратимость. Попробуй восстановить исходные три мапа из результата, и сразу увидишь неоднозначность. В таком случае, если мердж всё равно стал необратим, зачем теперь плейсхолдеры? А без плейсхолдеров можно сделать проще и красивее.

Crocodoom ★★ ()
Последнее исправление: Crocodoom (всего исправлений: 1)
Ответ на: комментарий от Crocodoom

Мне в данном случае не нужна обратимость - и да, я понимаю, что обратно мне не собрать в исходные данные смердженные мап-ы

Суть задачи как раз в том, что представим каждую мап-у как сущность некоторую, мы агрегируем такие сущности в одну

При этом, если параметра нет у одной, то в агрегированном мне надо обозначить это - поставить плейсхолдер

По сути я строю матрицу из таких сущностей:

List(Map(a -> [1], b -> [2], c -> [5]),
     Map(b -> [4]),
     Map(a -> [3]))

Тогда матрица будет:

a b c
1 2 5
_ 4 _
3 _ _ 

И агрегирование выйдет в виде:

Map(a -> [1, _, 3], b -> [2, 4, _], c -> [5, _, _])

В таком виде - да, обратно из агрегированного состояния я не получу данные, но мне это, повторюсь, не надо.

aarexer ()
Ответ на: комментарий от aarexer

Тогда матрица будет:

a b c
1 2 5
_ 4 _
3 _ _ 

И агрегирование выйдет в виде:

Map(a -> [1, _, 3], b -> [2, 4, _], c -> [5, _, _])

Как раз здесь всё обратимо и понятно. Из результата ты восстанавливаешь матрицу, и из неё — исходный список мапов.

А вот как только в исходных мапах у тебя вместо Map(a -> [1], b -> [2]) появляются Map(a -> [1,2,3], b -> [2,4]), то обратимость портится. И матрица уже не матрица, а непонятно что. Ну если это не проблема, то ок.

Crocodoom ★★ ()
Последнее исправление: Crocodoom (всего исправлений: 1)