Как отсортированный метод работает в Swift наоборот? - PullRequest
0 голосов
/ 16 декабря 2018
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]


func backward(_ s1: String, _ s2: String) -> Bool {
     return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

Поскольку аргументы передаются в обратную функцию, трудно понять, что происходит.Как работает этот код?

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

@ ответ Мэтта отлично.Пожалуйста, оставьте это как принятый ответ.Я хотел бы немного подробнее остановиться на этом.

Когда вы передаете свою функцию backward в sorted(), за кадром, в коде, который вы не видите, она вызывает backward несколько разсравнить два предмета.Чтобы раскрыть это поведение, добавьте оператор print к backward:

func backward(_ s1: String, _ s2: String) -> Bool {
     print("backward comparing \(s1) and \(s2)")
     return s1 > s2
}

Затем, когда вы запустите:

var reversedNames = names.sorted(by: backward)

, вы увидите:

backward comparing Alex and Chris
backward comparing Ewa and Alex
backward comparing Ewa and Chris
backward comparing Barry and Alex
backward comparing Barry and Chris
backward comparing Daniella and Alex
backward comparing Daniella and Barry
backward comparing Daniella and Chris
backward comparing Daniella and Ewa

Таким образом, даже если мы не видим код sorted(), он явно вызывает backward несколько раз, чтобы сравнить элементы для их сортировки.

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


Пример: сортировка вставкой

Давайте рассмотрим реальную сортировкуАлгоритм и как он использует функцию сортировки, которую вы передаете ему.

Ниже приведена реализация сортировки вставкой, которая является очень простым алгоритмом.Представьте, что вам дано пять игральных карт для сортировки.

  1. Положите карты на стол, а затем возьмите первую в левую руку.Карты в левой руке - это отсортированные карты.Поскольку у вас есть только одна, карты в левой руке сортируются по умолчанию.
  2. Теперь возьмите вторую карту правой рукой и вставьте ее в нужное место в левой руке.Для этого вам нужно сравнить карту в правой руке с картами в левой руке, чтобы найти правильную точку вставки.Поскольку у вас есть только две карты, вам просто нужно сравнить их, чтобы решить, будет ли новая карта до или после первой карты.
  3. Продолжите этот процесс, подбирая карту и вставляя ее в нужное место для каждой карты.карты на столе, пока вы не держите все карты в левой руке.
  4. Карты в левой руке теперь отсортированы.

Вот сортировка вставок:

// Sort array by building up the sorted result array, inserting the
// items one at a time into the result array which is always sorted
func insertionSort(array original: [String], by comesBefore: (String, String) -> Bool) -> [String] {
    // start the result array off with the first item from the
    // original
    var result = original.isEmpty ? [] : [original.first!]

    // For every other item in the original array, find out where
    // it goes and insert it there
    for item in original.dropFirst() {
        // Have we found the insertion point?
        var found = false

        // The current insertion point into the result array
        var newidx = 0

        // Loop while we haven't found the insertion point for the
        // current item and we haven't reached the end of the result
        // array
        while !found && newidx < result.count {
            // call the passed-in function to decide if the new item comes
            // before the current item of the result array
            if comesBefore(item, result[newidx]) {
                // Great!  The current item comes before result[newidx],
                // so we now know where to insert it
                found = true
            } else {
                // Item doesn't come before result[newidx], so let's move
                // on to the next index
                newidx += 1
            }
        }

        // Having found the insertion point, insert item into the result
        // array
        result.insert(item, at: newidx)
    }

    // Return the result array which now contains all of the items
    // which have been sorted by inserting them into the correct spots
    return result
}

Теперь запустите его:

let reversedNames = insertionSort(array: names, by: backward)
backward comparing Alex and Chris
backward comparing Ewa and Chris
backward comparing Barry and Ewa
backward comparing Barry and Chris
backward comparing Barry and Alex
backward comparing Daniella and Ewa
backward comparing Daniella and Chris
print(reversedNames)
["Ewa", "Daniella", "Chris", "Barry", "Alex"]

Итак, вы видите, что переданная вами функцияinsertionSort() используется для определения порядка пунктов.Как сказал @matt, принимая функцию, сортировка позволяет вам решить , что предшествует значению .

0 голосов
/ 16 декабря 2018

Метод sorted, отправленный в массив, получает элементы этого массива попарно и решает, какой из них стоит первым.Применяя это ко всем элементам массива, он заканчивается отсортированным массивом.

Но что значит «на первом месте»?Это может означать что угодно !Дело в том, вы можете решить, что это значит.Чтобы сообщить методу sorted, что означает «прибывает первым», вы передаете ему в качестве аргумента функцию, которая принимает два элемента и возвращает Bool, говорящий о том, «первый элемент« приходит первым ».

Ну, backward - это такая функция:

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}

Функция backward сообщает: первый аргумент «приходит первым» по отношению ко второму аргументу, только если он больше.

Теперь мыпередать функцию backward методу sorted:

var reversedNames = names.sorted(by: backward)

Обратите внимание, что backward нет вызова для функции backward;это имя функции backward.Мы передаем саму функцию sorted, чтобы она знала, что означает «приходит первым».

Итак, sorted в конечном итоге возвращает массив, где каждый более крупный элемент «идет первым» по отношениюк каждому меньшему элементу.Для строк «больше» означает «позже в алфавите», поэтому мы получаем ["Ewa", "Daniella", "Chris", "Barry", "Alex"].

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