Сгладить список кортежей Anorm

#scala #anorm

#scala #anorm

Вопрос:

Учитывая список scala, такой как:

 List( ~(OuterObj,InnerObj1), ~(OuterObj, InnerObj2), ...) 
  

Там, где все OuterObj одинаковы, а InnerObj могут быть разными, мне нужно «сгруппировать» это в один объект OuterObj, который содержит список InnerObj.

Другими словами, OuterObj имеет пустой атрибут innerList , но мне нужно преобразовать исходный список в один OuterObj таким образом, чтобы:

 OuterObj.innerList = List(InnerObj1, InnerObj2, ....)
  

Я пытался использовать .groupBy(_._1) , но это не сгруппировало объекты должным образом, и я не был уверен, куда идти дальше.

В случае, если контекст помогает, исходный список является результатом запроса объединения Anorm с отношением один ко многим (от 1 внешнего элемента ко многим внутренним элементам) с использованием следующего шаблона синтаксического анализатора:

 SQL(" joining outer on inner sql using a left join.. ").as(OuterObj.parse ~ InnerObj.parse *) // this is what creates the list of tuples
  

Ответ №1:

 tuples                            // List[(A, B)]
    .groupBy(_._1)                // Map[A , List[(A, B)]
    .mapValues(_.map(_._2))       // Map[A, List[B]]
    .toList                       // List[(A, List[B])]
    .map{ case (parent, children) =>
        parent.copy(
            innerList = children
        )
    }                             // List[A]
  

Используя внешнее соединение, вам действительно следует необязательно анализировать внутренние объекты, иначе вы потеряете строки, в которых нет внутренних объектов (если это не является желаемым эффектом). В этом случае вы бы сделали:

 SQL(...).as(OuterObj.parse ~ (InnerObj.parse ?) *) // List[(A, Option[B])]                    
    .groupBy(_._1)                // Map[A , List[(A, Option[B])]
    .mapValues(_.map(_._2))       // Map[A, List[Option[B]]]
    .toList                       // List[(A, List[Option[B]])]
    .map{ case (parent, children) =>
        parent.copy(
            innerList = children.flatten
        )
    }                             // List[A]
  

Комментарии:

1. Я использую левое внешнее соединение. Я думал, что это помешает мне потерять строки, когда внутренние объекты отсутствуют? И вы правы, я не хочу терять строки «outer», когда у них нет соответствующего «inner»

2. Правильно. Запрос сохранит строки, но анализатор не будет, если он не видит внутренний объект (когда внутренний анализатор не является необязательным).

3. Это работает до вызова mapValues: он возвращает Map[A, List[A]] . Кажется, это устраняет B (внутренний объект)

4. ах, я исправил это, изменив map на: .map( ._2) вместо .map( ._1)

5. Упс. Извините за это. Опечатка.