按字符和长度排序字符串

时间:2016-04-08 18:37:18

标签: sorting kotlin

在我的Android应用中,我尝试按顺序1,2,3 ...等排序总线路由标记。

为此我正在使用这个

Collections.sort(directions, Comparator { lhs, rhs ->
        var obj1 = lhs.short_names.firstOrNull() ?: ""
        var obj2 = rhs.short_names.firstOrNull() ?: ""

        if (obj1 === obj2) {
            obj1 = lhs.headsigns.firstOrNull() ?: ""
            obj2 = rhs.headsigns.firstOrNull() ?: ""
            if (obj1 === obj2) {
                return@Comparator 0
            }
            obj1.compareTo(obj2)
        } else {
            obj1.compareTo(obj2)
        }

我遇到的问题是对它们进行排序,但会遇到问题 1,2,3,30,31,4,5

我应该如何更改以获得正确的顺序。

1 个答案:

答案 0 :(得分:7)

如果您只需要一个简单的数字比较,就可以这样做。

directions.sortWith(Comparator { lhs, rhs ->
  val i1 = lhs.toInt()
  val i2 = rhs.toInt()
  when {
    i1 < i2 -> -1
    i1 > i2 -> 1
    else -> 0
  }
})

正如hotkey指出的那样,上面的代码可以用几乎相同的实现来代替,看起来更简单。

directions.sortBy { it.toInt() }

此算法的一般版本称为alphanum排序,详细描述here。我制作了这个算法的Kotlin端口,你可以使用它。它比你需要的更复杂,但它会解决你的问题。

class AlphanumComparator : Comparator<String> {
  override fun compare(s1: String, s2: String): Int {
    var thisMarker = 0
    var thatMarker = 0
    val s1Length = s1.length
    val s2Length = s2.length

    while (thisMarker < s1Length && thatMarker < s2Length) {
      val thisChunk = getChunk(s1, s1Length, thisMarker)
      thisMarker += thisChunk.length

      val thatChunk = getChunk(s2, s2Length, thatMarker)
      thatMarker += thatChunk.length

      // If both chunks contain numeric characters, sort them numerically.
      var result: Int
      if (isDigit(thisChunk[0]) && isDigit(thatChunk[0])) {
        // Simple chunk comparison by length.
        val thisChunkLength = thisChunk.length
        result = thisChunkLength - thatChunk.length
        // If equal, the first different number counts.
        if (result == 0) {
          for (i in 0..thisChunkLength - 1) {
            result = thisChunk[i] - thatChunk[i]
            if (result != 0) {
              return result
            }
          }
        }
      } else {
        result = thisChunk.compareTo(thatChunk)
      }

      if (result != 0) {
        return result
      }
    }

    return s1Length - s2Length
  }

  private fun getChunk(string: String, length: Int, marker: Int): String {
    var current = marker
    val chunk = StringBuilder()
    var c = string[current]
    chunk.append(c)
    current++
    if (isDigit(c)) {
      while (current < length) {
        c = string[current]
        if (!isDigit(c)) {
          break
        }
        chunk.append(c)
        current++
      }
    } else {
      while (current < length) {
        c = string[current]
        if (isDigit(c)) {
          break
        }
        chunk.append(c)
        current++
      }
    }
    return chunk.toString()
  }

  private fun isDigit(ch: Char): Boolean {
    return '0' <= ch && ch <= '9'
  }
}

要使用此Comparator,请致电

directions.sortWith(AlphanumComparator())

如果您不需要在Kotlin中对其进行编码,则可以在Dave Koelle's page上使用原始Java版本。此算法的Kotlin版本也可以在GitHub上找到。