在Swift中,我可以编写一个通用函数来调整数组的大小吗?

时间:2017-03-15 21:59:18

标签: swift

我有这个功能:

func sizeArray(inout array:Array<String>, size:Int) {

    while (array.count < size) {
        array.append("")
    }

    while (array.count > size) {
        array.removeLast()
    }
}

它可以工作,但只能使用Array of String,我可以使它适用于任何类型吗?

4 个答案:

答案 0 :(得分:4)

最通用的方法......

  1. Array适应RangeReplaceableCollection协议,其中包含可帮助调整大小的方法。 (无需使用循环)

  2. 在增长数组时,需要构造元素的新实例。所以你要么提供一个默认值......

  3. extension RangeReplaceableCollection {
        public mutating func resize(_ size: IndexDistance, fillWith value: Iterator.Element) {
            let c = count
            if c < size {
                append(contentsOf: repeatElement(value, count: c.distance(to: size)))
            } else if c > size {
                let newEnd = index(startIndex, offsetBy: size)
                removeSubrange(newEnd ..< endIndex)
            }
        }
    }
    
    var f = ["a", "b"]
    f.resize(5, fillWith: "")    // ["a", "b", "", "", ""]
    f.resize(1, fillWith: "")    // ["a"]
    
    1. 或者您创建了一个提供默认值init()的协议。请注意,您需要手动调整协议以适应您关注的每种类型。
    2. public protocol DefaultConstructible {
          init()
      }
      
      extension String: DefaultConstructible {}
      extension Int: DefaultConstructible {}
      // and so on...
      
      extension RangeReplaceableCollection where Iterator.Element: DefaultConstructible {
          public mutating func resize(_ size: IndexDistance) {
              resize(size, fillWith: Iterator.Element())
          }
      }
      
      var g = ["a", "b"]
      g.resize(5)
      g.resize(1)
      

答案 1 :(得分:1)

您可以创建泛型函数并为新元素提供默认值:

func sizeArray<T>(array: inout [T], size:Int, defaultValue: T) {

    while (array.count < size) {
        array.append(defaultValue)
    }

    while (array.count > size) {
        array.removeLast()
    }
}

var a = [1,2,3]
sizeArray(array: &a, size: 5, defaultValue: 0)

print(a)

答案 2 :(得分:1)

我对你的方法进行了一次调整。正如@Hamish在评论中提到的那样,你不能用字符串填充任何类型的数组,所以我也将'填充'传递给函数。

func sizeArray<T>(_ array:inout Array<T>, with filler:T, to size:Int) { 
    while (array.count < size) {
      array.append(filler)
    }
    while (array.count > size) {
      array.removeLast()
    }
}
var ints:[Int] = []
sizeArray(&ints, with: 3, to: 3)

var strings:[String] = ["a","b","c","d"]
sizeArray(&strings, with: "E", to: 3)

我还更新了参数名称以匹配Swift conventions

答案 3 :(得分:1)

这是扩展的完美工作

extension Array {
    mutating func resize(to size: Int, with filler: Element) {
        let sizeDifference = size - count
        guard sizeDifference != 0 else {
            return
        }
        if sizeDifference > 0 {
            self.append(contentsOf: Array<Element>(repeating: filler, count: sizeDifference));
        }
        else {
            self.removeLast(sizeDifference * -1) //*-1 because sizeDifference is negative
        }
    }

    func resized(to size: Int, with filler: Element) -> Array {
        var selfCopy = self;
        selfCopy.resize(to: size, with: filler)
        return selfCopy
    }
}

var ints: [Int] = [1]
ints.resize(to: 3, with: 3)
print(ints) //"[1, 3, 3]"

var strings = ["a","b","c","d"]
var resizedStrings = strings.resized(to: 3, with: "E")
print(strings) //"["a", "b", "c", "d"]"
print(resizedStrings) //"["a", "b", "c"]"

正确处理价值语义,并且没有任何不必要的循环。