如何对两个名称的字符串数组进行排序并将它们放回一起,以保持排序的完整性?

时间:2019-06-26 17:17:14

标签: arrays scala sorting

我正在获取一个文本文件,每行上都有名称,并尝试根据姓氏的长度(优先级),然后是名字的长度(第二优先级)对它们进行排序。结果应该是姓氏,并且看起来像这样,以x表示的字符:

xx xx, xx xxx, xx xxxx, xxx xx xxx xxx, xxxx xxx, 等

我的思维过程是将字符串按空格分开并单独排序。我尝试使用列表和地图没有运气。我目前正在使用数组方法来尝试维护分隔字符串的完整性。我可以按字符串长度对两个数组进行排序,但是我不知道如何在不弄乱顺序的情况下再次组合它们。

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 个答案:

答案 0 :(得分:1)

这是一种将“ 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)的精确顺序进行。  随意重新排列您认为合适的顺序。

答案 1 :(得分:1)

您不需要执行两种排序,而是需要使用实现所需排序功能的函数来进行单个排序。可能看起来像这样:

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)

这是一个使逻辑清晰的简单版本。如果效率是一个问题,则可能需要将名称拆分为元组,对元组进行排序,然后将它们重新组合在一起。您还应该计算一次长度,然后进行比较。

答案 2 :(得分:1)

您的描述含糊不清,与您提供的示例结果不符,但我想知道您追求的是这样的事情吗。

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

警告:仅当名称为2个字符串时,此方法才有效。它不会处理“梵高”之类的姓氏。