2013-11-15 3 views
0

У меня есть for-comprehension с генератором из Set[MyType] Этого MyType имеет lazy val переменную factsPair, которая возвращает пару наборов: (Set [MyFact], установите [ MyFact]).сплющивание набора пара множеств к одной паре множеств

Я хочу пропустить все их и объединить факты в одну сплющенную пару (Установить [MyFact], Установить [MyFact]) следующим образом, однако я получаю и not enough arguments for flatten: implicit (asTraversable ... ошибок. (Я немного новичок в Scala, так что все еще пытаюсь привыкнуть к ошибкам).

lazy val allFacts = 
(for { 
    mytype <- mytypeList 
} yield mytype.factsPair).flatten 

Что мне нужно указать для сглаживания для этого?

ответ

1

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

Вы можете, конечно, просто разделить, сглаживаются, и присоединиться снова:

val pairs = for { 
    mytype <- mytypeList 
} yield mytype.factsPair 
val (first, second) = pairs.unzip 
val allFacts = (first.flatten, second.flatten) 
+1

или:' val (first, second) = pairs.unzip'? – dhg

+0

Спасибо за ваши ответы! – jbx

+0

@dhg, поэтому я могу просто изменить 'flatten' на' unzip' в моем решении? У меня уже есть набор пар, проходящих через понимание, поэтому, если я правильно понимаю, unzip объединит их в одну пару наборов? – jbx

0

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

List((1,2), (3,4)).flatten   // bad 
List(List(1,2), List(3,4)).flatten // good 
+0

Спасибо. У меня есть Set ((Set (1,2), Set (3,4)), (Set (5,6), Set (7,8))) 'и результат, который я хочу, -' (Set (1, 2,5,6), Set (3,4,7,8)). Я предполагаю, что все гнездование меня сбило с толку. – jbx

3

Scala flatten работает на тех же самых типах. У вас есть Seq [(Set [MyFact], Set [MyFact])], который нельзя сгладить.

Я бы рекомендовал изучать функцию foldLeft, потому что это очень общий и очень проста в использовании, как только вы получите повесить его:

lazy val allFacts = myTypeList.foldLeft((Set[MyFact](), Set[MyFact]())) { 
    case (accumulator, next) => 
    val pairs1 = accumulator._1 ++ next.factsPair._1 
    val pairs2 = accumulator._2 ++ next.factsPair._2 
    (pairs1, pairs2) 
} 

Первый параметр принимает начальный элемент будет добавляемых другой элементы для. Начнем с пустого Tuple[Set[MyFact], Set[MyFact]], инициализированного следующим образом: (Set[MyFact](), Set[MyFact]()).

Далее мы должны указать функцию, которая берет аккумулятор и присоединяет к нему следующий элемент, и возвращает с новым аккумулятором, который имеет следующий элемент в нем. Из-за всех кортежей это выглядит не очень хорошо, но работает.

+0

Спасибо. Ваш ответ был немного более продолжительным, но мне все же хорошо понять, что происходит. – jbx

+0

@jbx Это не просто длинный, но он выполняет задание за один проход, а не несколько. Это обычно преимущество 'foldLeft' в том, что вы можете написать столько магии в тело, сколько хотите :) –

0

Я хотел бы предложить более алгебраический вид. То, что у вас здесь, может быть хорошо разрешено с помощью monoids. Для каждого моноида есть нулевой элемент и операция для объединения двух элементов в один.

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

Scalaz определяет моноиды для наборов, а также кортежи, поэтому нам ничего не нужно делать. Нам просто нужен вспомогательная функция, которая сочетает в себе несколько элементов моноидных в один, который легко реализуется с помощью складывания:

def msum[A](ps: Iterable[A])(implicit m: Monoid[A]): A = 
    ps.foldLeft(m.zero)(m.append(_, _)) 

(возможно, там уже есть такая функция в Scala, я не нашел). Использование msum мы можем легко определить

def pairs(ps: Iterable[MyType]): (Set[MyFact], Set[MyFact]) = 
    msum(ps.map(_.factsPair)) 

с использованием неявных моноиды Scalaz для кортежей и множеств.