Как я могу отсортировать два строковых массива имен и соединить их вместе, поддерживая целостность сортировки? - PullRequest
0 голосов
/ 26 июня 2019

Я беру текстовые файлы с именами в каждой строке и пытаюсь отсортировать их по длине фамилии (первый приоритет), а затем длины имени (второй приоритет).Результатом должно быть имя и фамилия, которые должны выглядеть следующим образом: символы, представленные символами x:

xx xx, xx xxx, xx xxxx, xxx xx, xxx xxx, xxxx xxx и т. Д.

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

val fnbuild = new ArrayBuffer[String]()
val lnbuild = new ArrayBuffer[String]()
val fullbuild = new ArrayBuffer[String]()

for (line <- Source.fromFile(filename).getLines){
  val split = line.split(" ")
  fullbuild += line
  //array of full names, first name first
  fnbuild += split(0)
  //array of first names
  lnbuild += split(1)
  //array of last names
}
val fnarray = fnbuild.toArray.sortWith(_.length < _.length)
val lnarray = lnbuild.toArray.sortWith(_.length < _.length)
val refarray = fullbuild.toArray

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

Ответы [ 3 ]

1 голос
/ 26 июня 2019

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

def nameOrder(a: String, b: String) = {
  val s1 = a.split("\\s+")
  val s2 = b.split("\\s+")

  if (s1.tail.length == s2.tail.length) {
    s1.head.length < s2.head.length
  } else {
    s1.tail.length < s2.tail.length
  }
}

val lines = Source.fromFile(filename).getLines

lines.sortWith(nameOrder)

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

1 голос
/ 26 июня 2019

Ваше описание расплывчато и не соответствует результатам, приведенным вами в качестве примера, но мне интересно, подходит ли вам нечто подобное.

io.Source.fromFile(filename)
         .getLines
         .toArray
         .sortBy{ line =>
           val Array(fn,ln) = line.split(" ")
           (ln.length, fn.length)
         }

Предупреждение: это будет работать, только если имя состоит из 2 строк. Он не будет обрабатывать фамилии, такие как «Ван Гог».

1 голос
/ 26 июня 2019

Вот один подход, который отображает "fname lname" в Tuple из (lname.length, lname, fname.length, fname), за которым следует sorted, как показано ниже:

// /path/to/file:
// John Doe
// Rachel Johnson
// Mike Dunn
// Jenn Smith
// David Smith

import scala.io.Source

val sortedNames = Source.fromFile("/path/to/file").getLines.
  map{ line =>
    val a = line.split("\\s+")
    (a(1).length, a(1), a(0).length, a(0))
  }.toVector.
  sorted.
  map(t => t._2 + " " + t._4)
// sortedNames: scala.collection.immutable.Vector[String] =
//    Vector(Doe John, Dunn Mike, Smith Jenn, Smith David, Johnson Rachel)

Обратите внимание, что сортировка будет выполняться в точный порядок элементов в кортеже (т.е. lname's length, lname, fname's length, fname).Не стесняйтесь изменить порядок, как считаете нужным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...