统一Swift中的数组和数组切片

时间:2015-07-16 17:01:08

标签: arrays swift generics

我对Swift非常陌生,对Apple编程也是如此。我写了这段代码来做二分搜索。

DataStructure <type1, type2, type3,...> mydatastruct = new DataStructure <String, Integer, String> () 

我在递归调用上遇到语法错误,因为第二个参数的类型为func binarySearch<X:Comparable> (needle:X, haystack:[X])->X? { if haystack.isEmpty { return nil } let mid = haystack.count / 2 let found = haystack[mid] if found == needle { return needle } else if found < needle { return binarySearch(needle, haystack[0..<mid]) } else { return binarySearch(needle, haystack[mid+1..<haystack.count]) } } ,而不是ArraySlice<X>

我通过使用相同的版本重载binarySearch来解决这个问题,除了第二个参数是Array<X>类型。

如果可以在一个功能中完成,我认为会更优雅。是否有合适的类型统一Array和ArraySlice?我尝试使用ArraySlice<X>,但由于某些原因,没有计数成员。我在文档中找到自己的方法仍然有些困难,所以我可能很容易忽略了一个更好的选择。

你能建议一个好方法吗?如果涉及使用内置课程,您是否可以给我一个如何在下次为自己找到它的提示,而不是写给SO?

2 个答案:

答案 0 :(得分:3)

要解决您的初始问题,请使用切片调用Array构造函数以获取数组:

func binarySearch<X:Comparable> (needle:X, haystack:[X])->X? {
    if haystack.isEmpty { return nil }
    let mid = haystack.count / 2
    let found = haystack[mid]
    if found == needle {
        return needle
    }
    else if needle < found {
        return binarySearch(needle, Array(haystack[0..<mid]))
    }
    else {
        return binarySearch(needle, Array(haystack[mid+1..<haystack.count]))
    }
}

此外,您的情况应为if needle < found

答案 1 :(得分:2)

是的,Array / ArraySlice很烦人。您需要的基本通用要求详见this问题。但是,为了满足您的要求,遗憾的是您必须获得一些非常可怕的功能签名。但是, 是可能的:

func bSearch<
  S : Sliceable where S.SubSlice : Sliceable,
  S.SubSlice.Generator.Element == S.Generator.Element,
  S.SubSlice.SubSlice == S.SubSlice,
  S.Generator.Element : Comparable,
  S.Index : IntegerArithmeticType,
  S.Index : IntegerLiteralConvertible,
  S.SubSlice.Index == S.Index
  >(el: S.Generator.Element, list: S) -> S.Generator.Element? {

    if list.isEmpty { return nil }

    let midInd = list.endIndex / 2

    let midEl: S.Generator.Element = list[midInd] // type inference giving me some bugs here

    if midEl == el {
      return el
    }

    return midEl < el ?
      bSearch(el, list: list[midInd+1..<list.endIndex]) :
      bSearch(el, list: list[0..<midInd])
}

对于Swift 1.2,只需更换机身:

if isEmpty(list) { return nil }

let midInd = list.endIndex / 2

let midEl: S.Generator.Element = list[midInd] // type inference giving me some bugs here

if midEl == el {
  return el
}

return midEl < el ?
  bSearch(el, list[midInd+1..<list.endIndex]) :
  bSearch(el, list[0..<midInd])