S3 URI генератор из комбинаций - PullRequest
0 голосов
/ 18 марта 2020

Мне нужно сделать генератор URI, который использует следующий шаблон в качестве входных данных s3://base/key1=s/key2={1,2,3}/key3={4,5} и получить из него 6 URI:

s3://base/key1=s/key2=1/key3=4
s3://base/key1=s/key2=1/key3=5
s3://base/key1=s/key2=2/key3=4
s3://base/key1=s/key2=2/key3=5
s3://base/key1=s/key2=3/key3=4
s3://base/key1=s/key2=3/key3=5

Звучит как общий комбинатор, но мне не удалось быстро найти существующий в Scala. Google отправляет мне geeksforgeeks в качестве примера, который я передаю на Scala в качестве следующего кода, пожалуйста, помогите мне сделать его короче / лучше:

def generateUrls(template: String) = {
  val re = """\{[,\w]+\}""".r
  val pattern = re.replaceAllIn(template, "%s")
  val options = new ListBuffer[Array[String]]
  for (m <- re.findAllIn(template)) {
    options += m.substring(1, m.length - 1).split(',').toSet.toArray
  }

  val sets = combinator(options)
  for(set <- sets)
    yield pattern.format(set:_*)
}

def combinator[T](arr:ListBuffer[Array[T]]):Seq[Seq[T]]= {

  //number of arrays
  val n = arr.size

  //to keep track of next element
  //in each of the n arrays
  val indices = Array.fill(n)(0)
  val result = new ListBuffer[Seq[T]]
  while (true) {
    //prcurrent combination
    result+= arr.zipWithIndex.map( r => r._1(indices(r._2)))
    //find the rightmost array that has more
    //elements left after the current element
    //in that array
    var next = n - 1
    while (next >= 0 && indices(next) + 1 >= (arr(next).size))
      next-=1

    //no such array is found so no more
    //combinations left
    if (next < 0)
      return result
    //if found move to next element in that
    // array
    indices(next) += 1

    //for all arrays to the right of this
    // array current index again points to
    // first element
    for (i <- next + 1 to n-1)
      indices(i) = 0
  }
  return result
}

1 Ответ

1 голос
/ 18 марта 2020

Если я правильно понимаю ваш вопрос ...

Использовал flatMap и map для построения List кортежей, используя два списка, приведенных в качестве входных данных, затем возьмите эти кортежи и соберите строки с использованием интерполяции строк.

def generateUrls(keys2: List[String], keys3: List[String]): List[String] = {
  keys2.flatMap(k2 => keys3.map(k3 => (k2,k3))).map(t => s"s3://base/key1=s/key2=${t._1}/key3=${t._2}")
}

scala> generateUrls(List("1","2","3"), List("4","5"))
res8: List[String] = List(
  s3://base/key1=s/key2=1/key3=4,
  s3://base/key1=s/key2=1/key3=5,
  s3://base/key1=s/key2=2/key3=4,
  s3://base/key1=s/key2=2/key3=5,
  s3://base/key1=s/key2=3/key3=4,
  s3://base/key1=s/key2=3/key3=5)
...