草庐IT

swift - 在 Swift 中采用 CollectionType(集合)

coder 2023-09-14 原文

我正在编写一个图形库以在图形中显示数据。由于我所做的大多数项目都倾向于在其中包含大量学习组件,因此我决定创建一个通用类型的结构来管理我的数据集 DataSet<T: Plottable> (注意这里 Plottable 也是 Comparable )。

试图符合 MutableCollectionType ,我遇到了一个错误。我想使用 sort() 的默认实现, 但编译器在尝试使用排序功能时给出以下错误。

Ambiguous reference to member 'sort()'

这是一个代码示例:

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

编译器建议了两个候选项,但不会实际显示给我。请注意,如果我显式实现 sort(),编译器错误就会消失在我的结构上。

但我还有更大的问题。我没有看到我希望默认实现提供什么?还是我在 Swift 3 中遇到了一个错误(这种情况很少见……通常我忽略了一些东西)。

这是结构的平衡:

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 })
}
}

最佳答案

您的数据集是一个双向集合。您尝试使用的 sort() 需要一个 RandomAccessCollection。您需要添加的最重要的事情是 Indicies 类型别名。

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,您实际上并不需要 Iterator。如果您实现 Collection,Swift 会自动为您提供 Sequence。

关于swift - 在 Swift 中采用 CollectionType(集合),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38810405/

有关swift - 在 Swift 中采用 CollectionType(集合)的更多相关文章

  1. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  2. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  3. python - 用于从 Python 到 Ruby 查找集合的所有分区的翻译函数 - 2

    我有以下python函数来递归查找集合的所有分区:defpartitions(set_):ifnotset_:yield[]returnforiinxrange(2**len(set_)/2):parts=[set(),set()]foriteminset_:parts[i&1].add(item)i>>=1forbinpartitions(parts[1]):yield[parts[0]]+bforpinpartitions(["a","b","c","d"]):print(p)有人可以帮我把它翻译成ruby​​吗?这是我目前所拥有的:defpartitions(set)ifnots

  4. C# 的 LINQ 用于在 ruby​​ 中等效的集合操作 - 2

    我是ruby​​开发的新手,我目前正在使用rails2.3.11在ruby​​1.8.7中开发一个项目,我想知道这种语言是否有与C#的linq等效的集合操作,例如where子句。谢谢。 最佳答案 Ruby中Linq的where等价于find_all检查documentationfortheEnumerableModule用于其他功能。 关于C#的LINQ用于在ruby​​中等效的集合操作,我们在StackOverflow上找到一个类似的问题: https://

  5. ruby-on-rails - Rails 表单对象与 reform-rails 与集合不工作或验证 - 2

    我正在使用reform-railsgem为了在我的Rails项目中使用表单对象。我意识到表单对象对于我在下面使用的示例代码来说可能有点矫枉过正,但它仅用于演示目的。在我创建一个用户的表单中,与该用户记录关联的是两个user_emails。#models/user.rbclassUser请注意,我没有在User模型中使用accepts_nested_attributes_for:user_emails。在我看来,表单对象的要点之一是它可以帮助您摆脱使用accepts_nested_attributes_for,所以这就是为什么我试图在没有它的情况下这样做。我从thisvideo得到了这个

  6. ruby - @users 变量为空。忘记为 will_paginate 传递集合对象? - 2

    问题localhost:3000/users/不会显示我谦虚地进入,因为我是第一次尝试通过Rails教程。我在第10章,我已经花了5个小时解决这个问题。当我尝试访问localhost:3000/users/时出现错误(我相信这与factory_girl有关)解释了@users变量为空并且我忘记了为will_paginate传递一个集合对象。我目前在第10章第10.23节,每次运行时:$bundleexecrakedb:reset$bundleexecrakedb:populate$bundleexecrakedb:test:prepare我在解释时遇到错误rakeaborted!Fac

  7. ruby - 使用 Mechanize gem 根据链接在 DOM 中的位置返回链接集合 - 2

    我正在为Mechanize而苦苦挣扎。我希望“单击”一组只能通过其位置(div#content中的所有链接)或其href来识别的链接。以上两种识别方法我都试过了,都没有成功。从文档中,我无法弄清楚如何根据链接在DOM中的位置而不是直接通过链接上的属性返回一组链接(用于单击)。其次,documentation建议你可以使用:href来匹配部分href,page=agent.get('http://foo.com/').links_with(:href=>"/something")但我让它返回链接的唯一方法是传递一个完全限定的URL,例如page=agent.get('http://foo

  8. ruby-on-rails - Ruby/Rails 集合到集合 - 2

    我有两个表与一个连接表连接-这只是伪代码:LibraryBookLibraryBooks我需要做的是,如果我有一个图书馆的id,我想获取该图书馆拥有的所有书籍所在的所有图书馆。因此,如果我有图书馆1,而图书馆1中有书A和B,而书A和B在图书馆1、2和3中,是否有优雅的(单行)方式在rails中执行此操作?我在想:l=Library.find(1)allLibraries=l.books.libraries但这似乎行不通。有什么建议吗? 最佳答案 l=Library.find(:all,:include=>:books)l.books

  9. ruby-on-rails - Rails 路由 : Nested, 成员、集合、命名空间、范围和可定制 - 2

    我想了解更多关于Rails路线的信息。成员和收藏#Exampleresourceroutewithoptions:resources:productsdomemberdoget'short'post'toggle'endcollectiondoget'sold'endend命名空间和作用域#Exampleresourceroutewithinanamespace:namespace:admindoresources:productsendscope:admindoresources:productsend约束,Redirect_to#Exampleresourceroutewithop

  10. ruby-on-rails - 如何在递归方法中使用预加载集合 - 2

    我有以下自指关联:classAction我的问题是should_finish和should_start正在互相调用,即使我预加载了父级,它仍然会导致许多查询:Action.includes(:parents).last.should_finish#anewqueryeverytimeitchecksforparents关于如何缓存actions和parents有什么想法吗?编辑-让我提供一些背景信息:#actionstable:actions_parentstable:#id|durationtask_id|parent_id#1|52|1#2|103|1#3|204|2#4|154|

随机推荐