2016-08-07 80 views
2

我正在編寫一個圖形庫來在圖形中顯示數據。由於我所做的大部分項目都傾向於在其中包含大量學習組件,因此我決定創建一個通用類型的結構來管理我的數據集DataSet<T: Plottable>(這裏請注意,Plottable也是Comparable)。在Swift中採用CollectionType(Collection)

爲了符合MutableCollectionType,我遇到了一個錯誤。我想使用sort()的默認實現,但編譯器在嘗試使用排序功能時出現以下錯誤。

曖昧參考成員 '排序()'

下面是一個代碼示例:

var data = DataSet<Int>(elements: [1,2,3,4]) 
data.sort() //Ambiguous reference to member 'sort()' 

編譯器提出兩名候選人,但實際上並不會顯示它們給我。請注意,如果我在結構上明確實現了sort(),則編譯器錯誤消失。

但是更大的問題仍然存在。我沒有看到我期望默認實現提供什麼?或者我正在運行Swift 3中的一個bug(這種情況很少發生,通常我忽略了一些)。

下面是該結構的平衡:

struct DataSet<T: Plottable>: MutableCollection, BidirectionalCollection { 
typealias Element = T 
typealias Iterator = DataSetIterator<T> 
typealias Index = Int 

/** 
The list of elements in the data set. Private. 
*/ 
private var elements: [Element] = [] 

/** 
Initalize the data set with an array of data. 
*/ 
init(elements data: [T] = []) { 
    self.elements = data 
} 

//MARK: Sequence Protocol 
func makeIterator() -> DataSetIterator<T> { 
    return DataSetIterator(self) 
} 

//MARK: Collection Protocol 
subscript(_ index:DataSet<T>.Index) -> DataSet<T>.Iterator.Element { 
    set { 
     elements[index] = newValue 
    } 
    get { 
     return elements[index] 
    } 
} 

subscript(_ inRange:Range<DataSet<T>.Index>) -> DataSet<T> { 
    set { 
     elements.replaceSubrange(inRange, with: newValue) 
    } 
    get { 
     return DataSet<T>(elements: Array(elements[inRange])) 
    } 
} 

//required index for MutableCollection and BidirectionalCollection 
var endIndex: Int { 
    return elements.count 
} 
var startIndex: Int { 
    return 0 
} 
func index(after i: Int) -> Int { 
    return i+1 
} 
func index(before i: Int) -> Int { 
    return i-1 
} 

mutating func append(_ newElement: T) { 
    elements.append(newElement) 
} 

// /** 
//  Sorts the elements of the DataSet from lowest value to highest value. 
//  Commented because I'd like to use the default implementation. 
//  - note: This is equivalent to calling `sort(by: { $0 < $1 })` 
//  */ 
// mutating func sort() { 
//  self.sort(by: { $0 < $1 }) 
// } 
//  
// /** 
//  Sorts the elements of the DataSet by an abritrary block. 
//  */ 
// mutating func sort(by areInIncreasingOrder: @noescape (T, T) -> Bool) { 
//  self.elements = self.elements.sorted(by: areInIncreasingOrder) 
// } 

/** 
Returns a `DataSet<T>` with the elements sorted by a provided block. 

This is the default implementation `sort()` modified to return `DataSet<T>` rather than `Array<T>`. 

- returns: A sorted `DataSet<T>` by the provided block. 
*/ 
func sorted(by areInIncreasingOrder: @noescape (T, T) -> Bool) -> DataSet<T> { 
    return DataSet<T>(elements: self.elements.sorted(by: areInIncreasingOrder)) 
} 

func sorted() -> DataSet<T> { 
    return self.sorted(by: { $0 < $1 }) 
} 
} 

回答

3

數據集是一個BidirectionalCollection。您正在嘗試使用的sort()需要一個RandomAccessCollection。您需要添加的最重要的東西是Indicies typealias。

typealias Indices = Array<Element>.Indices 

這裏是我的版本的類型:

protocol Plottable: Comparable {} 
extension Int: Plottable {} 

struct DataSet<Element: Plottable>: MutableCollection, RandomAccessCollection { 
    private var elements: [Element] = [] 

    typealias Indices = Array<Element>.Indices 

    init(elements data: [Element] = []) { 
     self.elements = data 
    } 

    var startIndex: Int { 
     return elements.startIndex 
    } 

    var endIndex: Int { 
     return elements.endIndex 
    } 

    func index(after i: Int) -> Int { 
     return elements.index(after: i) 
    } 

    func index(before i: Int) -> Int { 
     return elements.index(before: i) 
    } 

    subscript(position: Int) -> Element { 
     get { 
      return elements[position] 
     } 
     set { 
      elements[position] = newValue 
     } 
    } 

    subscript(bounds: Range<Int>) -> DataSet<Element> { 
     get { 
      return DataSet(elements: Array(elements[bounds])) 
     } 
     set { 
      elements[bounds] = ArraySlice(newValue.elements) 
     } 
    } 
} 

var data = DataSet(elements: [4,2,3,1]) 
data.sort() 
print(data.elements) // [1,2,3,4] 

你實際上並不需要一個Iterator,如果你不想要一個。如果你實現了Collection,Swift會自動給你序列。

相關問題