Scala с использованием foldLeft для вставки терминатора между списком строк

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

Например List("a", "b", "c", "d") с терминатором ; будет в конечном итоге a;b;c;d;

Вот мой foldLeft который я думаю, хорошо, но мой terminateLeft не работает по какой-то странной причине, любая идея?

def foldLeft [A,B] (xs:List[A], e:B, f:(B,A)=>B) : B = {
  def auxFoldLeft(xs: List[A], e: B) : B = {
    xs match {
      case Nil => e
      case x::xs => auxFoldLeft(xs, f(e, x))
    }
  }
  auxFoldLeft(xs, e)
}

def joinTerminateLeft (xs : List[String], term : String) : String = {
  def f(s: String, s2: String) : String = s + s2
  xs match {
    case Nil => ""
    case x::xs => x + foldLeft(xs, term, f)
  }
}

Когда я бегу joinTerminateLeft с a, b, c, d он останавливается после B по какой-то причине и выводит строки c, d, но не с терминатором.

2 ответа

Решение

Что происходит, так это то, что вы используете термин в качестве начального значения. Но e является аккумулятором, каждая итерация добавляет к последней. Так что пройдите один раз, и вы получите ; + b но в следующий раз аккумулятор это значение того, чтобы вы получили |b + c

Что вам нужно, это другая функция. Вместо добавления значения к аккумулятору, вам нужно добавить термин к значению, а затем добавить его к аккумулятору.

def joinTerminateLeft (xs : List[String], term : String) : String = {
  def f(s: String)(s2: String, s3: String) : String = s2 + s + s3
  xs match {
    case Nil => ""
    case x::xs => x + foldLeft(xs, "", f(term))
  }
}

Вот фрагмент кода, который работает:

def joinTerminateLeft (xs : List[String], term : String) : String = {
    def f(s: String, s2: String) : String = s + term + s2
    xs match {
        case Nil => ""
        case x::xs => x + foldLeft(xs, "", f)
    }
}

Термин должен использоваться только внутри f, Вторым параметром foldLeft является значение инициализации, которое в этом случае должно быть пустым (уменьшение или что-то подобное было бы более уместным вместо сгиба, оставленного здесь).

Другие вопросы по тегам