skip to Main Content

I have a list of arrays look like this:

var lists = [[Category]]()

Each element in the "lists" represents an array of object (Category), I’m trying to reinit the "lists" (clear every element) after using it.

My approach:

lists.forEach { list in 
    list.removeAll()
}

Error: Can not mutate the "list" because "list" is a constant variable

Is there anyway I can achieve my goal in Swift?

5

Answers


  1. You can assign an empty array literal which is written as [ ] (an empty pair of square brackets)

    lists = []
    

    lists is now an empty array, but still of type [[Category]]

    Login or Signup to reply.
  2. Since arrays are value types and they have copy-on-write semantics, "clearing all the nested arrays of an array" is indistinguishable from "creating a new array with as many empty nested arrays as there are nested arrays in the old array, and reassigning it to the old array".

    So you can do

    lists = Array(repeating: [], count: lists.count)
    

    Alternatively:

    lists = lists.map { _ in [] }
    

    From the comments, it seems like you are writing a function that clears all the nested arrays. In that case, you need an inout parameter:

    func clearList(_ lists: inout [[Category]]) {
        lists = Array(repeating: [], count: lists.count)
    }
    

    And to call it:

    var myLists = [listCate1, listCate2]
    clearList(&myLists)
    // myLists will be [[], []], note that this does not change listCate1 or listCate2
    

    If you really want your function to mutate an arbitrary number of lists that you pass in, you’d need to use unsafe pointers (very not recommended):

    func clearList(_ lists: UnsafeMutablePointer<[Category]>...) {
        for list in lists {
            list.pointee = []
        }
    }
    

    And clearList(&listCate1, &listCate2) would actually change listCate1 and listCate2, but this is a rather dirty trick.

    Login or Signup to reply.
  3. You can remove all the element of an array and keep the capacity.

    lists.removeAll(keepingCapacity: true)
    

    or if you want to remove object from array based on some conditions then you can use this…

    lists.removeAll { (obj) -> Bool in
    
       if <check some condition {   return true  }
       else { false  }
       
     }
    
    Login or Signup to reply.
  4.     var someInts1 = [30,11,34]
        var someInts2 = [30,11,34]
        var someInts3 = [30,11,34]
    
        var lists = [Any]()
        lists = [someInts1, someInts2, someInts3]
        print(lists) // [[30,11,34], [30,11,34], [30,11,34]]
    
        lists = [] // this is where the list become empty
        print(lists) // []
    
    Login or Signup to reply.
  5. I’d create an extension with mutable and immutable variants. By extending RangeReplaceableCollection rather than Array we don’t need to constrain Array.Element to any specific type.

    extension RangeReplaceableCollection where Element: RangeReplaceableCollection {
        func stripped() -> Self {
            return .init(repeating: .init(), count: count)
        }
    
        mutating func strip() {
            self = stripped()
        }
    }
    

    Now we can strip in place if our array is declared mutable:

    var mutable: [[Category]] = []
    mutable.strip()
    

    Or we can use the immutable variant for let constants:

    let immutable: [[Category]] = []
    let stripped = immutable.stripped()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search