Распаковка списка Scala

#scala #functional-programming

#scala #функциональное программирование

Вопрос:

Итак, моя проблема проста. Я сталкивался с этим много раз, и мой мозг не может найти решение.

Как я могу распаковать список в другой список для неопределенного количества переменных?

Вот что я имею в виду.

 
val list1 = List(List(7, 4), List(7, 6))

val list2 = List(List(1), List(5), List(8))

val desired_list1 = List(List(1, 7, 4), List(5, 7, 4), List(8, 7, 4))

val desired_list2 = List(List(1, 7, 6), List(5, 7, 6), List(8, 7, 6))

//** The desired_list1 and 2 must be a List[List[Int]] it cannot be List[List[Any]] 

//Here's my attempt, which oddly enough completely ignores all elements of list1(0) which are not the first(7).

val attempt = list2.map(i => i  : list1(0)).map(j => j.collect{ case k:Int => k; case l @ a :: b => a}).map(m => m.map{ case i:Any => i.toString.toInt})

//The result is 

attempt: List[List[Int]] = List(List(1, 7), List(5, 7), List(8, 7))

//while it should be:

val desired_list1 = List(List(1, 7, 4), List(5, 7, 4), List(8, 7, 4))

  

Мне нужен способ распаковки, который не является ручным, пожалуйста, не говорите мне делать это:

 
val attempt = list2.map(k => k  : list1(0)).map{ case (k, List(x, y)) => (k, x, y)}

  

В принципе, list1 может содержать любое количество элементов. например

 val list1 = List(List(99, 83, 2, 3, 4), List(99, 83, 2, 5 7))
  

Однако эти числа никогда не повторяются, поэтому я думаю, что это также может быть набор. Но я мало что знаю о наборах или о том, поможет ли это каким-либо образом.

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

1. Разве это не просто val desired_list1 = list2.map(k => k : list1(0)) , второго map не требуется?

2. Нет, потому что тогда это станет List(List(1, List(7, 4)) , например

3. Нет, это не сработает, попробуйте: scalafiddle.io/sf/aBvAKMR/1 . Конечно, ваше текущее редактирование делает его другим, используйте .

Ответ №1:

Кажется, это то, что вы хотите:

 val lists: List[List[Int]] = List(List(7, 4), List(7, 6))    
val prefixes: List[List[Int]] = List(List(1), List(5), List(8))

val res: List[List[Int]] = for{
  prefix <- prefixes.flatten
  rest <- lists
} yield prefix :: res

// res: List[List[Int]] = List(List(1, 7, 4), List(1, 7, 6), List(5, 7, 4), List(5, 7, 6), List(8, 7, 4), List(8, 7, 6))
  

Если только вам действительно не нужен список, содержащий ваши desired_list1 и desired_list2 вместе, и в этом случае вам нужно:

 val res3 = lists.map{ rest => 
  prefixes.flatten.map{prefix =>
    prefix :: rest
  }
}

/// res3: List[List[List[Int]]] =
// List(
//  List(
//      List(1, 7, 4), List(5, 7, 4), List(8, 7, 4)
//  ), 
//  List(
//      List(1, 7, 6), List(5, 7, 6), List(8, 7, 6)
//  )
// )
  

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

1. Спасибо!. Будет ли это работать распределенным образом? например, с Spark и RDD?

2. Это совершенно другая проблема, и я не уверен, что у меня достаточно данных, чтобы дать вам правильный ответ на нее.

3. В любом случае спасибо. Я забыл добавить, что на самом деле list2 должен быть: val list2 = List(List(1), List(5), List(8))

4. для этого просто нужен .flatten . Обновлен ответ. Если это отвечает на ваш вопрос, отметьте его ответом, пожалуйста. Спасибо

Ответ №2:

Я не совсем уверен, почему вы этого хотите, но попробуйте это:

 val list1 = List(List(7, 4), List(7, 6))
val list2 = List(1, 5, 8)

list2.flatMap(element=> list1.map(innerList=> element:: innerList))
  

вывод: Список[List[Int]] = Список(Список(1, 7, 4), Список(1, 7, 6), Список (5, 7, 4), Список (5, 7, 6), Список (8, 7, 4), Список(8, 7, 6))

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

1. Estou a desenvolver um novo algoritmo para achar as minimal transversals de um hypergraph, e isto faz parte do mesmo.