Scala - объединение двух списков кортежей по общим элементам - PullRequest
0 голосов
/ 06 мая 2018

Как объединить два списка кортежей, которые имитируют Соотношение Чазлов?

(а, б), (б, в) => (а, в)

Вот пример:

val l1 = List(("Dan", "b"), ("Dan","a"), ("Bart", "c"))
val l2 = List(("a", "1"), ("c", "1"), ("b", "3"), ("a", "2"))

Ожидаемый результат будет:

val result = List(("Dan", "3"), ("Dan", "1"), ("Dan", "2"), ("Bart", "1"))

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Для каждого кортежа в l1 вы можете отфильтровать l2, чтобы выбрать кортежи с соответствующим первым элементом:

def join[A, B, C](l1: List[(A, B)], l2: List[(B, C)]): List[(A, C)] = {
  for {
    (key, subkey) <- l1
    value <- l2.collect { case (`subkey`, value) => value }
  } yield key -> value  
}

Вы также можете заранее преобразовать l2 в Map для лучшей производительности выбора:

def join[A, B, C](l1: List[(A, B)], l2: List[(B, C)]): List[(A, C)] = {
  val valuesMap = l2.groupBy(_._1)
  for {
    (key, subkey) <- l1
    (_, value) <- valuesMap.getOrElse(subkey, Nil)
  } yield key -> value  
}
0 голосов
/ 06 мая 2018

Вы в основном хотите рассмотреть все пары одного элемента из первого списка и одну из второго и сохранить те, где элементы "b" совпадают.

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

l1.map(x => l2.map(y => (x,y))

Это не совсем верно, так как теперь у нас есть List[List[((String, String),(String,String))]] - нам нужно плоское отображение:

l1.flatMap(x => l2.map(y => (x,y)))

Теперь нам нужно отфильтровать, чтобы сохранить только те пары, которые мы хотим, и привести в порядок:

l1.flatMap(x => l2.map(y => (x,y)))
  .filter{ case ((_,y),(b,_)) => y == b }
  .map {case ((x, _),(_,c)) => (x,c) }

что дает нам

List((Dan,3), (Dan,1), (Dan,2), (Bart,1))

Это был довольно неприятный беспорядок, и мы можем немного его исправить - давайте отфильтруем l2 в нашем оригинальном flatmap и построим результат там, чтобы нам не пришлось манипулировать кортежем кортежи:

l1.map{ case (x,y) => 
    l2.filter{ case (b, _) => y == b}
      .map{ case (_, c) => (x, c)} }

Это один из тех случаев, когда легче читать for понимание:

for {
  (x, y) <- l1
  (b, c) <- l2
  if y == b
} yield (x,c)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...