通用数组上的函数

时间:2015-06-23 14:08:58

标签: swift generics functional-programming

我想在Swift中使用更多函数式编程。我编写的一些函数可以在各种类型的数组上很好地工作。我不想用不同的类型(或typealases)重写相同的函数。函数的工作方式通常是相同的,只是使用不同的类型。所以,我试过这样的事情:

// Add indeces to an array of any type. I.e., returns an array of tuples of the array index and the original element.
func addIndeces<T: AnyObject>(toArray: Array<T>) -> Array<(index: Int, value: T)> {
    var arrIndex: [Int] = []
    for index in 0...toArray.count {
        arrIndex.append(index)
    }   
    return Array(Zip2(arrIndex, toArray))
}

当我调用此函数时

// Note: reminderList is of type [Reminder]
let indexedReminderList = addIndeces(reminderList) as! [(index: Int, reminder: Reminder)]

我收到运行时错误:“致命错误:不能在不同大小的类型之间使用unsafeBitCast”

我做错了什么?

3 个答案:

答案 0 :(得分:2)

你正在写的功能已经存在 - 有点像。 enumerate“返回包含对{la> n , x )的惰性SequenceType,其中 n \ s是连续的{ {1}} \ s从零开始, x \ s是Int

的元素

这意味着您可以将您的功能编写为:

base

注意,您不需要编写func addIndices<T>(toArray: [T]) -> [(index: Int, reminder: T)] { // if you want to label the tuple elements index: and reminder:, // you still have to use map: return map(enumerate(toArray)) { (index: $0, reminder: $1) } } ,除非具体想要阻止此函数接受除类数组之外的任何内容(因为T: AnyObjectAnyObject - 只有类,而不是结构或枚举符合的协议。)

注意,enumerate仅适用于整数索引集合。为了使其更通用,您可以编写zip(indices(someCollection),someCollection))indices返回任何集合的所有索引的范围,因此等同于someCollection.startIndex..<someCollection.endIndex

答案 1 :(得分:1)

您希望将Array类型为[(index: Int, value: T)]的元组T转换为类型为Reminder的元组Array [(index: Int, reminder: Reminder)] 。所以你可以看到元组有不同的元素名称(值和提醒),两者都有不同的字节大小 - 因此错误。

因此,您应该为两个元组使用相同的元素名称。

如果要更改元素名称:

let newTupleArray = oldTupleArray.map{ (newElementName0: $0.0, newElementName1: $0.1) }

答案 2 :(得分:0)

范围0...toArray.count包含从0到toArray计数的所有元素,包括计数值,在您的情况下,arrIndex将始终有一个元素,然后是toArray。这是造成不同尺寸错误的原因。要解决此问题,请使用此0..<toArray.count

替换您的范围