Есть ли в Scala способ конвертировать Seq [(String, String)] в Seq [String]? - PullRequest
0 голосов
/ 13 октября 2019

Я новичок в Scala и действительно кодирую в целом, так что извините, если этот вопрос немного прост, но мне нужна помощь!

В настоящее время у меня есть функция, которая выдает Seq[(String, String)], которую я тогда хотел быпреобразовать в Seq[String].

В зависимости от итерации функции размерность вектора будет разной, поэтому некоторые результаты равны Seq[(String, String)], другие - Seq[(String, String, String)] и т. Д. Поэтому в идеале я мог бы использовать одну и ту же функцию для каждого выхода.

Я пытался использовать .flatten и split[","] и не уверен, какие еще методы я мог бы использовать.

Для одного значения выборки вывод функции выглядит следующим образом:

res17: Seq[(String, String)] = Vector((u, v),(w, x))

Идеальный результат будет Vector(u,v,w,x)

Ответы [ 2 ]

1 голос
/ 13 октября 2019

Рассмотрим бесформенный подход, который обеспечивает способ абстрагирования над арностью типобезопасным способом:

import shapeless._
import shapeless.ops.hlist
import syntax.std.tuple._

def flattenTupleN[P <: Product, L <: HList](
  ps: List[P]
)(implicit gen: Generic.Aux[P, L],
  toT: hlist.ToTraversable.Aux[L, List, String]
): List[String] = {
  ps.flatMap(p => gen.to(p).toList) 
}

val t1: List[(String, String)] = List(("u", "v"), ("w", "x"))
val t2: List[(String, String, String)] = List(("a", "b", "c"), ("d", "e", "f"))
val t3: List[(Int, Double, String)] = List((42, 3.14, "Picard"))

flattenTupleN(t1)
flattenTupleN(t2)
// flattenTupleN(t3) // compile-time error

, который выводит

res0: List[String] = List(u, v, w, x)
res1: List[String] = List(a, b, c, d, e, f)

Здесь небезопасноно нестандартный подход:

def flattenTupleNUnsafe(ps: List[Product]): List[String] =
  ps.flatMap(_.productIterator.map(_.toString))

flattenTupleNUnsafe(t1)
flattenTupleNUnsafe(t2)
flattenTupleNUnsafe(t3) // compiles OK but is a bad idea!

, который выводит

res2: List[String] = List(u, v, w, x)
res3: List[String] = List(a, b, c, d, e, f)
res4: List[String] = List(42, 3.14, Picard)

Обратите внимание, что из-за потери безопасности типов flattenTupleNUnsafe(t3) компилируется очень хорошо и вводит логическую ошибкув программе.

0 голосов
/ 13 октября 2019

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

Пожалуйста, обдумайте, что я хочу сказать в предварительном свете, так как я не знаю достаточно очто вы пытаетесь сделать.

Вы говорите, что выводимый вами кортеж может варьироваться. Рассматривали ли вы преобразование всего из Tuple в Vector?

Так что вместо

res17: Vector[(String, String)] = Vector((u, v),(w, x))

используйте

res17: Vector[Vector[String]] = Vector(Vector(u, v),Vector(w, x))

Вы можете легко преобразовать вектор Vector водин вектор с вызовом flatMap или flatten, который, основываясь на вашем вопросе, звучит так, как будто вы уже знаете, как это сделать.

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

Так что вместо Tuple2 или Tuple3 определите иерархию наследования, которая позволяет компиляторудля проверки типа вашей программы.

Примерно так:

trait MyData

case class 2MemberData(data1: String, data2: String) extends MyData

case class 3MemberData(data1: String, data2: String, data3: String) extends MyData

case class 4MemberData(data1: String, data2: String, data3: String, data4: String) extends My Data

Таким образом, ваша функция может выводить значение типа Vector [MyData], которое затем выровняется с помощью сопоставления с образцом. Так что-то вроде

def processData: Vector[MyData]

def cleanUp(input: Vector[MyData]): Vector[String]

, где cleanUp реализован следующим образом:

def cleanUp(input: Vector[MyData]): Vector[String] = {
  input.flatMap{ d =>
    d match {
      case 2MemberData(data1, data2) => Vector(data1, data2)
      case 3MemberData(data1, data2, data3) => Vector(data1, data2, data3)
      case 4MemberData(data1, data2, data3, data4) => Vector(data1, data2, data3, data4)
    }
  }
}

Я просто выкидываю идеи и не знаю, полезно ли то, что я говорю, или нет,Это действительно зависит от того, как выглядит окружающий код. Если у вас есть какие-либо вопросы, не стесняйтесь спрашивать.

...