2015-12-23 3 views
2

Я хотел бы реализовать «наивный» вид в быстром. Я делаю так:Функции и генерические средства

extension Array { 
    func sort<Element: Comparable>(isOrderedBefore: (Element, Element) -> Bool) -> [Element] { 

     var sortedArray : [Element] = [] 
     for x in self { 
      for (index, value) in sortedArray.enumerate() { 
       if isOrderedBefore(x, value) { 

       } 
      } 
     } 
     return sortedArray 
    } 
} 

У меня есть ошибки компиляции: «не может ссылаться на isOrderedBefore со списком аргументов«(элемент, элемент)

Если удалить Comparable протокол, код компилируется, но я . не может реализовать функцию сортировки без элементов, входящих массивов были сопоставимы

Этот код компилируется:

extension Array { 
    func sort(isOrderedBefore: (Element, Element) -> Bool) -> [Element] { 

     var sortedArray : [Element] = [] 
     for x in self { 
      for (index, value) in sortedArray.enumerate() { 
       if isOrderedBefore(x, value) { 

       } 
      } 
     } 
     return sortedArray 
    } 
} 

Что я делаю неправильно?

+1

Почему вы думаете, что вы * не можете реализовать функцию сортировки без Элементы массива сопоставимы *? Поскольку вы предоставляете пользователю возможность предоставить пользовательскую функцию сравнения, нет необходимости указывать, что общий тип должен быть сопоставим. – luk2302

+0

Расширение Массив где Элемент: Сопоставимый {... –

+0

@ luk2302 Вы правы, нет необходимости соответствовать протоколу Comparable. – samir

ответ

1

Общие типы вашей функции сортировки сталкиваются с уже существующим общим типом массива Element. Расширения неявно имеют те же параметры типа, что и базовый тип. Ваша функция sort не нуждается в параметрах типа, поскольку она уже знает, что такое Element.

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

Итак, я добавил достаточно кода для вашего примера, чтобы заставить его работать (я также изменил имя, чтобы не столкнуться с существующим sort()).

extension Array { 
    func mySort(isOrderedBefore: (Element, Element) -> Bool) -> [Element] { 

     var sortedArray : [Element] = [] 
     for x in self 
     { 
      var inserted = false 
      for (index, value) in sortedArray.enumerate() where !inserted 
      { 
       if isOrderedBefore(x, value) 
       { 
        sortedArray.insert(x, atIndex: index) 
        inserted = true 
       } 
      } 
      if !inserted 
      { 
       sortedArray.append(x) 
      } 
     } 
     return sortedArray 
    } 
} 

Теперь я могу использовать его. Если у меня есть массив Ints, соответствующие стандартам Сопоставимые, я могу использовать операторы сравнения, как isOrderedBefore

// Because I am using Int in the array, I can use > as the "closure" because 
// its type is (Int, Int) -> Bool 
let sorted = [1, 2, 6, 4, 3].mySort(>) 

print("\(sorted)") // [6, 4, 3, 2, 1] 

Если у меня есть тип, который не Сопоставимые, мне нужно что-то другое. Так....

struct Person: CustomStringConvertible 
{ 
    let name: String 
    let age: Int 

    var description: String { return "\(name) aged \(age)" } 
} 

Попытка использовать оператор сравнения является ошибкой, поскольку Person не сравним

let foo = [ Person(name: "Fred", age: 12), 
      Person(name: "Alice", age: 20), 
      Person(name: "Pat", age: 15)].mySort(<) // Error! 

Но

let foo = [ Person(name: "Fred", age: 12), 
      Person(name: "Alice", age: 20), 
      Person(name: "Pat", age: 15)].mySort{ $0.age < $1.age } 

print("\(foo)") // [Fred aged 12, Pat aged 15, Alice aged 20] 
0

В быстром 2.0 вы можете создать расширение для массива сопоставимого типа, как это:

extension SequenceType where Generator.Element : Comparable { 
    func dumbSort(isOrderedBefore: (Generator.Element, Generator.Element) -> Bool) -> [Generator.Element] { 

     var sortedArray : [Generator.Element] = [] 
     for x in self{ 
      for (_, value) in sortedArray.enumerate() { 
       if isOrderedBefore(x, value) { 
        // do what you planned to 
       } 
      } 
     } 
     return sortedArray 
    } 
} 
+0

Нет смысла использовать 'enumerate()', если вы проигнорируете его вывод индекса. – Alexander

2

а) массив соответствует CollectionType и косвенно SequenceType б) есть реализация по умолчанию рода, как часть SequenceType

extension SequenceType where Self.Generator.Element : Comparable { 
    /// Return an `Array` containing the sorted elements of `source`. 
    /// 
    /// The sorting algorithm is not stable (can change the relative order of 
    /// elements that compare equal). 
    /// 
    /// - Requires: The less-than operator (`func <`) defined in 
    /// the `Comparable` conformance is a 
    /// [strict weak ordering](http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings) 
    /// over the elements in `self`. 
    @warn_unused_result 
    public func sort() -> [Self.Generator.Element] 
} 

и

extension SequenceType { 
    /// Return an `Array` containing the sorted elements of `source` 
    /// according to `isOrderedBefore`. 
    /// 
    /// The sorting algorithm is not stable (can change the relative order of 
    /// elements for which `isOrderedBefore` does not establish an order). 
    /// 
    /// - Requires: `isOrderedBefore` is a 
    /// [strict weak ordering](http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings) 
    /// over the elements in `self`. 
    @warn_unused_result 
    public func sort(@noescape isOrderedBefore: (Self.Generator.Element, Self.Generator.Element) -> Bool) -> [Self.Generator.Element] 
} 

так, если реализация по умолчанию не достаточно для вас (если у вас есть какие-то особые требования относительно порядка элементов, которые сравнивают равны), вы можете следовать по тому же сценарию

extension SequenceType where Self.Generator.Element : Comparable { 
    public func mySpecialSort() -> [Self.Generator.Element] { 
     ... 
    } 
} 

и/или

extension SequenceType { 
    public func mySpecialSort(@noescape isOrderedBefore: (Self.Generator.Element, Self.Generator.Element) -> Bool) -> [Self.Generator.Element] { 
    ... 
} 
Смежные вопросы