0

I need to sort objects with strings that contains number and include language sort my object includes file, String file name, String isFolder.

and when I sort list of files in a folder

The list:

  1. "file name with default language"
  2. "file name 1"
  3. "file name 10"
  4. "file name 11"
  5. "file name 2"
  6. "file name 20"

How can I sort them like this:

  1. "file name with default language"
  2. "file name 1"
  3. "file name 2"
  4. "file name 10"
  5. "file name 11"
  6. "file name 20"

My code:

final Collator collator = Collator.getInstance(Locale.getDefault());
// listJFiles = ArrayList of my objects called "JFile"
listJFiles.sort((o1, o2) -> collator.compare(o1.isFolder + o1.fileName, o2.isFolder + o2.fileName));

(This one does not help - How to sort by two fields in Java? Because I need to sort also by language, and I don't know how to combine it with my code which does sort by language)

letsintegreat
  • 3,328
  • 4
  • 18
  • 39
J El
  • 100
  • 7
  • Does this answer your question? [How to sort by two fields in Java?](https://stackoverflow.com/questions/4805606/how-to-sort-by-two-fields-in-java) – Nir Alfasi Jan 24 '21 at 13:02

1 Answers1

1

Firstly, I’d like to write few words to explain the observed behaviour. It is correct and expected. String objects are compared character by character referring to an ordinal number of a character in the ASCII table (http://www.asciitable.com/). In case of two strings have identical start, the longer string is considered bigger. This is why "file name 10” is bigger than “file name 1” and “file name 2” is bigger than “file name 10”.

The behaviour you want to achieve requires to include one more factor to the comparison mechanism: to take numbers into account and compare them using arithmetical rules.

I suppose the case you posted as an example is partial and simple one: there is no number or only one number and it is always placed at the end of a string. Whereas a full problem may imply that a string may contain an arbitrary number of numbers located at any position.

I’ll give you a one possible solution to this problem, which solves the simple case (the one you described):

data class Item(val text: String)
data class SplitItem(val text: String, val number: Int?)

fun SplitItem.toItem() = Item(text + (number?.let { " $it" } ?: ""))

fun main() {
    val items = listOf(
        Item("file name with default language"),
        Item("file name 1"),
        Item("file name 10"),
        Item("file name 11"),
        Item("file name 2"),
        Item("file name 20")
    ).shuffled()

    val splitItems = items.map {
        val split = it.text.split(' ')

        try {
            val number = Integer.parseInt(split.last())
            SplitItem(
                text = split.dropLast(1).joinToString(separator = " "),
                number = number
            )
        } catch (e: NumberFormatException) {
            SplitItem(
                text = it.text,
                number = null
            )
        }
    }

    val sortedItems = splitItems.sortedWith { o1, o2 ->
        val n = compareValues(o1.number, o2.number)
        val t = compareValues(o1.text, o2.text)
        compareValues(n, t)
    }

    sortedItems
        .map { it.toItem() }
        .forEach { println(it) }

}

Which produces the next output:

Item(text=file name with default language)
Item(text=file name 1)
Item(text=file name 2)
Item(text=file name 10)
Item(text=file name 11)
Item(text=file name 20)

To solve the full problem I’d suggest you to evolve this approach.

YTerle
  • 2,606
  • 6
  • 24
  • 40
  • i'm in java sorry... (i don't know kotlin) Really sorry, thanks anyway for trying... – J El Jan 24 '21 at 16:34