#scala #apache-spark
#scala #apache-spark
Вопрос:
У меня есть класс case
case class DDD(abc: String, v1: String, v2: String)
и у меня есть кортеж, основанный на DDD (схеме). Итак, представьте это
val sample1 = DDD("a1", "v0001", "v0002")
и затем я создаю карту из значений этого кортежа следующим образом
val tMap = Map("col_name" -> sample1.abc, "col_old" -> sample1.v1, "col_new" -> sample1.v2)
Но могут быть случаи, когда мои значения v1 или v2 в моих кортежах могут быть пустыми / null / empty, и если значение отсутствует, я не хочу добавлять эту пару ключ-значение на мою карту, поэтому
Например
If
val sample2 = DDD("a1", "null", "v0002")
Then
val tMap = Map("col_name" -> sample1.abc, "col_new" -> sample1.v2)
Я могу достичь этого, просто используя условие if, как показано ниже
val sample2 = DDD("a1", "null", "v0002")
val tMap = Map("col_old" -> (if(sample2.v1 != "null") sample2.v1),
"col_new" -> (if(sample2.v2 != "null") sample2.v2
"abc" -> (if(sample2.abc != "null") sample2.abc
)
Но нужно сделать и понять, как я могу достичь этого более чистым функциональным способом. ???
Спасибо
Комментарии:
1. Подсказка: вы можете определить объект класса case DDD, здесь вы пишете, что определяете свои вспомогательные конструкторы на основе ваших конкретных условий
Ответ №1:
Как насчет чего-то подобного?
case class DDD(abc: String, v1: String, v2: String)
val sample1 = DDD("a1", "null", "v0002")
val mapKeys = List("col_name", "col_old", "col_new")
val tMap =
(mapKeys.toIterator zip sample1.productIterator).collect {
case (k, v: String) if (v != "null")=> k -> v
}.toMap
// tMap: Map[String, String] = Map(col_name -> a1, col_new -> v0002)
Комментарии:
1. не хочу устанавливать mapKeys отдельно
2. @AJm В чем проблема с наличием ключей в виде внешнего списка?
3. У нас есть определенные стандарты кода, которым нужно следовать, это не будет принято
4. @AJm Какой стандарт кода запрещает это? По какой конкретной причине? — Кроме того, если вы не можете иметь ключи в виде какой-либо коллекции, не было бы никакого другого решения, кроме проверки условия и добавления значений одно за другим.
Ответ №2:
Почему бы вам не создать пользовательский метод unapply для этого класса case?
По умолчанию Scala создает одноэлементный объект, в котором указаны методы apply и unapply. Итак, вам следует создать еще один.
object DDD {
def unapply(arg: DDD): Map[String, String] = {
def mapIfNotNull(key:String, value:String):Option[(String, String)] = if (value == "null") None else Some(key -> value)
Seq(
mapIfNotNull("col_name", arg.abc),
mapIfNotNull("col_old", arg.v1),
mapIfNotNull("col_new", arg.v2)
).flatten.toMap
}
}
Затем вы можете использовать этот синглтон позже, чтобы отменить применение экземпляра класса case.
DDD.unapply(sample1)
Я думаю, что этот способ более чистый