Scala создать неизменную вложенную карту - PullRequest
1 голос
/ 17 февраля 2020

У меня есть ситуация здесь

У меня есть две строки

val keyMap = "anrodiApp,key1;iosApp,key2;xyz,key3"
val tentMap = "androidApp,tenant1; iosApp,tenant1; xyz,tenant2"

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

tenant1 -> (andoidiApp -> key1, iosApp -> key2),
tenant2 -> (xyz -> key3)

Так что в основном хочу группировать по арендатору и создать карту keyMap

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

case class TenantSetting() {
  val requesterKeyMapping = new mutable.HashMap[String, String]()
}

val requesterKeyMapping = keyMap.split(";")
      .map { keyValueList => keyValueList.split(',')
        .filter(_.size==2)
        .map(keyValuePair => (keyValuePair[0],keyValuePair[1]))
        .toMap
      }.flatten.toMap

    val config = new mutable.HashMap[String, TenantSetting]

    tentMap.split(";")
      .map { keyValueList => keyValueList.split(',')
        .filter(_.size==2)
        .map { keyValuePair =>
          val requester = keyValuePair[0]
          val tenant = keyValuePair[1]
          if (!config.contains(tenant)) config.put(tenant, new TenantSetting)
          config.get(tenant).get.requesterKeyMapping.put(requester, requesterKeyMapping.get(requester).get)
        }
      }

1 Ответ

2 голосов
/ 17 февраля 2020

Логика c для разбиения строк на карту может быть одинаковой для обоих, поскольку у них одинаковый синтаксис.

То, что вы использовали для первой строки, было не совсем правильным, так как фильтр, который вы применяли каждой строке из результата разбиения, а не в самом результате массива. Что также показало, что вы использовали [] на keyValuePair, который имел тип String, а не Array[String], как я думаю, вы ожидали. Также вам нужно было trim, чтобы справиться с пробелами во второй строке. Возможно, вы захотите также обрезать ключ и значение, чтобы избежать других проблем с пробелами.

Кроме того, в этом случае сочетание карты и фильтра можно сделать более кратко с помощью collect, как показано здесь: Как преобразовать массив в кортеж? Использование шаблона с 2 элементами гарантирует, что вы отфильтруете все, что угодно, кроме длины 2. iterator должен сделать комбинацию карты и сбора более эффективной, требуя только одну итерацию коллекции, возвращенной из первого split (см. Комментарии ниже). Обе строки превращаются в карту, просто нужно правильно использовать groupBy, чтобы сгруппировать первую карту по значению второй на основе того же ключа, чтобы получить то, что вы хотели. Очевидно, это работает только в том случае, если один и тот же ключ всегда находится на второй карте.

def toMap(str: String): Map[String, String] =
  str
    .split(";")
    .iterator
    .map(_.trim.split(','))
    .collect { case Array(key, value) => (key.trim, value.trim) }
    .toMap

val keyMap = toMap("androidApp,key1;iosApp,key2;xyz,key3")
val tentMap = toMap("androidApp,tenant1; iosApp,tenant1; xyz,tenant2")

val finalMap = keyMap.groupBy { case (k, _) => tentMap(k) }

Распечатка finalMap дает:

Map(tenant2 -> Map(xyz -> key3), tenant1 -> Map(androidApp -> key1, iosApp -> key2))

То, что вы хотели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...