10

Is there any way I can simplify this:

var unloadedImagesRows = [String:[Int]]()

private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    if unloadedImagesRows[forLocation] == nil {
                    unloadedImagesRows[forLocation] = [Int]()
    }
    unloadedImagesRows[forLocation]!.append(row)
}

Doesn't Swift have an easy way to check for nil, and if so, create a new object, and all subsequent uses refers to the object?

Blaszard
  • 30,954
  • 51
  • 153
  • 233
ikevin8me
  • 4,253
  • 5
  • 44
  • 84
  • 1
    Pretty sure your answer is the most simple swift has to offer. All the others here seem to be less simple and/or efficient. I dug for more than an hour on this and do not think there is a simpler way to express this. – Eric Mentele Apr 12 '16 at 08:31
  • Do you know of an example from another language that does this better? I am curious to know what inspired this question and if there is another way from another language, maybe propose a similar feature addition to Swift open source. – Eric Mentele Apr 12 '16 at 08:36

6 Answers6

8

You can simplify it into just one line:

private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    unloadedImagesRows[forLocation] = (unloadedImagesRows[forLocation] ?? []) + [row]
}
Eendje
  • 8,815
  • 1
  • 29
  • 31
2
var unloadedImagesRows = [String:[Int]]()

// if let
private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    if let _ = unloadedImagesRows[forLocation] {

    } else {
        unloadedImagesRows[forLocation] = [Int]()
    }
    unloadedImagesRows[forLocation]!.append(row)
}

// guard let
private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    guard let _ = unloadedImagesRows[forLocation] else {
        unloadedImagesRows[forLocation] = [Int]()
        return addToUnloadedImagesRow(row, forLocation: forLocation)
    }

    unloadedImagesRows[forLocation]!.append(row)
}

// nil coalescing
private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    var b = unloadedImagesRows[forLocation] ?? [Int]()
    b.append(row)
    unloadedImagesRows[forLocation] = b
}
Eric Mentele
  • 864
  • 9
  • 16
  • It looks like nil coalescing can only be used in one way because someone got the same answer I have for that one. Apparently he beat me to it while I was editing/working it out in a playground. Upvote! – Eric Mentele Apr 12 '16 at 08:15
2

You can create a helper operator for nil checks and use it like below.

infix operator ?= { associativity left precedence 160 }

func ?=<T: Any>(inout left: T?, right: T) -> T {
    if let left = left {
        return left
    } else {
        left = right
        return left!
    }
}

Here you will be able to use it like unloadedImagesRows[forLocation] ?= [Int]() if empty

var unloadedImagesRows = [String:[Int]]()

private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    unloadedImagesRows[forLocation] ?= [Int]()
    unloadedImagesRows[forLocation]!.append(row)
}

addToUnloadedImagesRow(1, forLocation: "This is something")

print(unloadedImagesRows) // "["This is something": [1]]\n"
Rahul Katariya
  • 3,528
  • 3
  • 19
  • 24
2

If you want to avoid if or guard you could try the nil coalescing operator (??).

private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    var rowsForLocation = unloadedImagesRows[forLocation] ?? [Int]();
    rowsForLocation.append(row)
    unloadedImagesRows[forLocation] = rowsForLocation
}

Note: This might not be very efficient since you have to re-assign the array to the dictionary. I'm not sure if this will result in a full copy of the array.

nebs
  • 4,939
  • 9
  • 41
  • 70
1

you can use if let or guard statement

  private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
      if let a = unloadedImagesRows[forLocation] as? [Int] {
           //...success block
      }
  }

or use guard statement

  private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
      guard let a = unloadedImagesRows[forLocation] else {
           return
      }
      //...
  }

for more info. check this link

Community
  • 1
  • 1
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
1

You can check it as follow.

private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
    if let image = unloadedImagesRows[forLocation] {
                //it is not nil
    } else {
        //it is nil
    }

}
Mahendra
  • 8,448
  • 3
  • 33
  • 56