2015-03-16 19 views
5

Cố gắng mở rộng loại mảng để sử dụng phân loại nhị phân để chèn các phần tử theo thứ tự. Đây là mã sân chơi của tôi:Mở rộng Swift Array đơn giản

extension Array { 

     func insertionIndexOf(elem: T , isOrderedBefore: (T, T) -> Bool) -> Int { 
     var lo = 0 
     var hi = self.count - 1 
     while lo <= hi { 
     let mid = (lo + hi)/2 
     if isOrderedBefore(self[mid], elem) { 
      lo = mid + 1 
     } else if isOrderedBefore(elem, self[mid]) { 
      hi = mid - 1 
     } else { 
      return mid 
     } 
    } 
     return 0 
} 


    mutating func insertOrdered(elem: T){ 
    let index = self.insertionIndexOf(elem, isOrderedBefore: { (a , b)  in return (a > b) }) 
    return insert(elem, atIndex: index) 
} 

}

tôi nhận được một lỗi biên dịch: "Không thể gọi insertionIndexOf với danh sách đối số kiểu (T, isOrderedBefore: (_, _) -> _)"

điều kỳ lạ là, nếu tôi sử dụng thay vì:.

mutating func insertOrdered(elem: T){ 
     let index = self.insertionIndexOf(elem, isOrderedBefore: { (a , b) in return false }) 
     return insert(elem, atIndex: index) 
     } 

trình biên dịch bình tĩnh lại nhưng chèn mảng sẽ không được ra lệnh, :(dĩ nhiên Xin vui lòng bất kỳ ý tưởng ?? Cảm ơn bạn.

(sử dụng Xcode 6.3 beta 2 - Swift 1.2)

+0

Mã đó trông quen thuộc http://stackoverflow.com/a/26679191/1187415 :) - Lưu ý rằng 'return 0' cuối cùng phải là' return lo'. –

+0

@MartinR Có :) Tôi đã sử dụng ví dụ của bạn cho tìm kiếm nhị phân để thêm ngữ cảnh vào vấn đề của tôi. Tôi đã chơi xung quanh với phần mở rộng một chút. Rất tiếc, bạn chỉ quên bỏ liên kết tới mã của mình. Hy vọng không có hại gì. –

+0

@MartinR http://stackoverflow.com/questions/29107928/swift-map-extension-for-set –

Trả lời

4

Bạn đang cố gắng để đánh giá a > b, nhưng T thể không Comparable. Nó không thể viết một phần mở rộng như thế này ngày hôm nay. Những gì bạn muốn có thể nói là:

extension Array where T: Comparable { 

Nhưng điều đó không thể thực hiện được trong Swift hiện tại. Nhóm biên dịch đã chỉ ra rằng nó là một ưu tiên, nhưng chúng tôi không biết khi nào nó có thể đến với Swift.

cách tiếp cận tốt nhất của bạn là một trong hai làm cho một chức năng:

func insertOrdered<T: Comparable>(inout xs: [T], x: T) 

Hoặc tạo ra một đối tượng mới mà HAS-A mảng:

struct OrderedArray<T: Comparable> : ... { 
    var values: [T] 
    func insertionIndexOf(elem: T , isOrderedBefore: (T, T) -> Bool) -> Int 
    mutating func inserOrdered(elem: T) 
    ... 
} 
+0

Cảm ơn một triệu Rob! Tôi sẽ thử đề xuất của bạn –

4

Tính Swift 2, điều này có thể đạt được với phương thức mở rộng giao thức:

extension CollectionType where Generator.Element : Comparable, Index == Int { 

    func insertionIndexOf(elem: Generator.Element) -> Int { 
     var lo = 0 
     var hi = self.count - 1 
     while lo <= hi { 
      let mid = (lo + hi)/2 
      if self[mid] < elem { 
       lo = mid + 1 
      } else if elem < self[mid] { 
       hi = mid - 1 
      } else { 
       return mid // found at position mid 
      } 
     } 
     return lo // not found, would be inserted at position lo 
    } 
} 

extension RangeReplaceableCollectionType where Generator.Element : Comparable, Index == Int { 

    mutating func insertOrdered(elem: Generator.Element) { 
     let index = self.insertionIndexOf(elem) 
     self.insert(elem, atIndex: index) 
    } 
} 

Ví dụ:

var ar = [1, 3, 5, 7] 
ar.insertOrdered(6) 
print(ar) // [1, 3, 5, 6, 7] 

Các phương pháp không được định nghĩa cho struct Array trực tiếp, nhưng đối với một số Nghị định thư nào Array chiếu theo, và cung cấp các phương pháp cần thiết.

Đối với phương pháp đầu tiên, đó là CollectionType vì điều đó cung cấp quyền truy cập chỉ số (đọc) và yếu tố thu là bắt buộc phải là Comparable.

Phương pháp thứ hai thay đổi bộ sưu tập, tại đây giao thức hạn chế hơn RangeReplaceableCollectionType là bắt buộc.

Các vấn đề liên quan