Как отсортировать массив как по номерам, так и по алфавиту в Swift - PullRequest
4 голосов
/ 06 апреля 2020

Скажем, у меня есть массив:

var array = ["5C", "4D", "2H", "13S", "4C", "5H"]

Как бы я мог отсортировать этот массив так, чтобы в новом массиве последний символ сортировался в алфавитном порядке, а затем предыдущий числовой числовые значения, такие как:

["4C", "5C", "4D", "2H", "5H", "13S"]

Я относительно новичок в кодировании в целом и имею очень простой c gr asp синтаксис. Другие поиски показали, как выполнять числовую сортировку с использованием функции .sorted и .ascendingOrder, но я не смог найти решение, которое могло бы сортировать как по алфавиту, так и по цифрам.

Ответы [ 4 ]

2 голосов
/ 06 апреля 2020

Вы должны написать свой собственный компаратор, который очень удобен в Swift.

Если последний символ совпадает, сортируйте строку без последнего символа, в противном случае сортируйте по последнему символу

let array = ["5C", "4D", "2H", "13S", "4C", "5H"]

let sortedArray = array.sorted { (str1, str2) -> Bool in
    if str1.suffix(1) == str2.suffix(1) {
        return str1.dropLast().localizedStandardCompare(str2.dropLast()) == .orderedAscending
    } else {
        return str1.suffix(1) < str2.suffix(1)
    }
}

// ["4C", "5C", "4D", "2H", "5H", "13S"]
1 голос
/ 06 апреля 2020

EDIT:

В моем ответе показано, как использовать sorted() для сортировки массива строк в порядке "нумерация c". Это не совсем то, что спросил ОП.

К ОП: Вы должны принять ответ Вадиана. Это был первый правильный ответ.

Однако я провожу некоторое время в своем ответе, объясняя синтаксис закрытия Swift, поэтому я собираюсь оставить ответ.


Вы можете использовать массив метод sorted(), который принимает замыкание, которое сравнивает пары объектов и возвращает true, если первый элемент должен стоять первым.

Тогда вы можете использовать метод NSString compare(options:), чтобы сделать "цифру c" сравнение строк, где последовательности цифр обрабатываются как числа внутри строки.

Вот фрагмент рабочего кода, который отсортирует ваш массив:

var array = ["5C", "4D", "2H", "13S", "4C", "5H"]

let sorted = array.sorted (by: { (first: String, second: String) -> Bool in
    return first.compare(second, options: .numeric) == .orderedAscending
})

Функция sorted() is a " функция более высокого порядка`, или функция, которая принимает другую функцию в качестве параметра. Для массива строк эта функция принимает 2 строки и возвращает Bool. На самом деле она принимает замыкание, а не функцию, где замыкание является «анонимным» function "(функция без имени.)

Адаптируя код vadian, который дает ПРАВИЛЬНЫЙ ответ на мой фрагмент, это будет выглядеть так:

var array = ["5C", "4D", "2H", "13S", "4C", "5H"]

let sorted = array.sorted (by: { (first: String, second: String) -> Bool in
    if first.suffix(1) == second.suffix(1) {
        return first.dropLast.compare(second, options: .numeric) == .orderedAscending

    } else {
        return first.suffix(1) < second.suffix(1)
    }
})
* 10 25 * Вы можете переписать вышеупомянутое с помощью нескольких сочетаний клавиш:

С помощью "конечного замыкания" вы пропускаете (), который содержит замыкание в качестве параметра, и просто предоставляете замыкание в фигурных скобках после имени функции.

Вы можете пропустить объявление параметров и возвращаемого типа замыкания, а также пропустить оператор возврата:

let sorted = array.sorted { $0.compare($1, options: .numeric) == .orderedAscending }

Для более сложного кода, такого как vadian, который дает правильный ответ, я предлагаю не используя позиционные параметры, как это. Использование локальных переменных, таких как first и second, облегчает чтение кода.

Я предлагаю внимательно изучить главу о замыканиях в Apple Swift iBooks, пока вы не поймете различные способы выражения замыканий и их различные сокращенные синтаксисы. Сначала это сбивает с толку, и использование замыканий является основополагающим для использования Swift.

0 голосов
/ 07 апреля 2020

Добро пожаловать в StackOverflow!

это мое решение, надеюсь, оно сработает для вас, я просто упорядочиваю сначала числа и затем сравниваю их с алфавитом для создания нового массива:

var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
    array = array.sorted { $0.numbersValues < $1.numbersValues }
    let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    var newArrray: [String] = [] 
    for letter in str {
            for value in array {
                if value.lettersValues.hasPrefix(String(letter)) {
                       newArrray.append(value)
                }
            }
    }

Не забудьте включить методы этого помощника в ваш проект

    extension String {

        var lettersValues: String {
            return self.components(separatedBy: CharacterSet.decimalDigits).joined()
        }

        var numbersValues: String {
            return self.filter { "0"..."9" ~= $0 }
        }
    }
0 голосов
/ 06 апреля 2020

Добро пожаловать в StackOverflow!

Что означают эти цифры? Я бы создал struct для моделирования этой "вещи" (сейчас я назову ее Thing) и функцию, которая может анализировать String в Thing, например:

struct Thing: Equatable { // FIXME: Name me something descriptive
    let number: Int // FIXME: Name me something descriptive
    let letter: Character // FIXME: Name me something descriptive

    static func parse(from string: String) -> Thing? {
        let numberSegment = string.prefix(while: { $0.isNumber })
        guard !numberSegment.isEmpty,
            let number = Int(numberSegment) else { return nil }

        let letterSegement = string.drop(while: { $0.isNumber })
        guard letterSegement.count == 1,
            let letter = letterSegement.first else { return nil }

        return Thing(number: number, letter: letter)
    }
}

Тогда вы можете просто соответствовать Comparable, определяя, как вы хотите, чтобы вещи сортировались, определяя оператор сравнения <:

extension Thing: Comparable {
    static func < (lhs: Thing, rhs: Thing) -> Bool {
        return (lhs.letter, lhs.number) < (rhs.letter, rhs.number)
    }
}

Оттуда, это просто вопрос синтаксического анализа все ваши строки в Thing s и сортировка их:

let array = ["5C", "4D", "2H", "13S", "4C", "5H"]

let things = array.map { Thing.parse(from: $0)! }
print("Before sorting:")
things.forEach { print("\t\($0)") }

let sortedThings = things.sorted()
print("\nAfter sorting:")
sortedThings.forEach { print("\t\($0)") }

Вывод:

Before sorting:
    Thing(number: 5, letter: "C")
    Thing(number: 4, letter: "D")
    Thing(number: 2, letter: "H")
    Thing(number: 13, letter: "S")
    Thing(number: 4, letter: "C")
    Thing(number: 5, letter: "H")

After sorting:
    Thing(number: 4, letter: "C")
    Thing(number: 5, letter: "C")
    Thing(number: 4, letter: "D")
    Thing(number: 2, letter: "H")
    Thing(number: 5, letter: "H")
    Thing(number: 13, letter: "S")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...