How to get value from array of arrays - swift

I have array of arrays grid in my code. what I want to do is checking if there is a object at x, y let object = grid[x][y] if object is not nil I edit it else I assign a new object to it grid[x][y] = newObject().
if let object = grid[x][y] {
object.property = newValue
} else {
grid[x][y] = newObject()
}
but I get fatal error: Array index out of range in the line if let object = grid[x][y] {
what is the best way to do that?
Thanks in advance.

What you need to do (as I said in my comment) is to both allocate the array to the size that you want, and to make it an array of Object? rather than Object (or Object! - why do you do that?). Something like this, for a 2x2 array ...
var grid = [[Object?]](count:2, repeatedValue: [Object?](count:2, repeatedValue:nil))

Firstly, if you want to modify your grid object down the road, you can't define it with let. You must use var.
It looks like you're trying to use optional binding (if let x = Optional(y) { ... }) with array subscripting (array[x]). This won't work, as an array subscript doesn't return an optional. It'll instead return a valid object or throw an exception. You could try this:
if grid.count > x {
if grid[x].count > y {
object = grid[x][y]
}
}

Related

Initialize dictionary from array with Swift 3

Is there a more simple/efficient way to initialize a dictionary from an array in Swift 3?
for object in array {
dict[object.id] = object
}
Nothing wrong with the above but I was wondering if you could use map/reduce/etc to do this with slightly less code.
array.forEach({ object in
dict[object.id] = object
})
or shorter:
array.forEach({ dict[$0.id] = $0 })

How to check if a value is nil or not from a Set<T>

I have a Set and now I'm trying to get an object in a index position:
var testItem: ExpandableCell
if let object = expandableCells[indexPath.row] {
testItem = object as! ExpandableCell
}
But I get an error.
UPDATE:
I just convert from SET to Array my collection class variable and now I have this:
let realItem : ExpandableCell?
if let testItem: AnyObject = expandableCells[indexPath.row] {
realItem = testItem as! ExpandableCell
print(realItem?.title)
}
It compiles without a problem but when i run the code and the index its outside of its boundaries then I get the following error:
So seems that my if let statement is not working.
Any clue?
Set is an unordered collection of unique objects. Because they're unordered, getting them by an Int index makes no sense.
Perhaps you meant to use an Array, an ordered collection of objects. Array doesn't guarantee the uniqueness of its objects, but it does preserver ordering, thus Int indexes make sense.
you can use loop Instead if/let condition
for testItem in expandableCells {
if let realItem = testItem as? ExpandableCell {
print(realItem?.title)
}
}

Can an empty array check somehow precede an optional binding?

Given that you have an array of optionals:
var values = [AnyObject?]
Can you use a where clause somehow before the optional binding, say, to check for a non-empty array? For example, I know that we can do this:
if !values.isEmpty {
if let value = values[0] {
// ...
}
}
And we can chain a where filter after the optional binding:
// doesn't do you any good when the array is empty
if let value = values[0] where !values.isEmpty {
// ...
}
I'd like to be able evaluate the where first, to prevent an array index out of range error:
// Not valid syntax
if where !values.isEmpty, let value = values[0] {
// ...
}
Is there some form of syntax in Swift 1.2 or 2.x that allows me to express this in a valid manner?
Very simple:
if let value = values.first {
...
}

Optional vs Bound value assigning var from array

I want to check if there is a value in a array and if so assign to a String using a if-left statement:
if let scoreValue = scoreValueArray[element!]{
// do something with scoreValue
}
Error: Bound value in a conditional binding must be of optional type
So tried changing the ! to ? but error persists.
Any input appreciated.
scoreValueArray is an array of strings, where a String value is appended to array if a condition is met, then array is saved to NSUserdefaults.
So element is a int which corresponds to a index in the array, bt only if the index is occupied with a String, so
scoreValueArray[element!]
could return an 'Index out of bounds', hence want to use the if-let.
Although the accepted answer clearly puts why optional binding is not available in the current implementation, it doesn't provide with a solution.
As it is shown in this answer, protocols provide an elegant way of safely checking the bounds of an array. Here's the Swift 2.0 version:
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
Which you can use like this:
let fruits = ["Apple", "Banana", "Cherry"]
if let fruit = fruits[safe: 4] {
// Do something with the fruit
}
It's not clear what type your scoreValueArray is, but for the sake of this answer, I'm going to assume it's an array of Int.
var scoreValueArray: Array<Int>
Now, if we look the definition of the Array struct, we'll find this:
struct Array<T> : MutableCollectionType, Sliceable {
// other stuff...
subscript (index: Int) -> T
// more stuff
}
So, calling the subscript method on our array (which is what we do when we say scoreValueArray) returns a non-optional. And non-optionals cannot be used in the conditional binding if let/if var statements.
We can duplicate this error message in a more simple example:
let foo: Int = 3
if let bar = foo {
// same error
}
This produces the same error. If we instead do something more like the following, we can avoid the error:
let foo: Int? = 3
if let bar = foo {
// perfectly valid
}
This is different from a dictionary, whose subscript method does return an optional (T?). A dictionary will return a value if the key passed in the subscript is found or nil if there is no value for the passed key.
We must avoid array-index-out-of-bounds exceptions in the same way we always do... by checking the array's length:
if element < scoreValueArray.count {
scoreValue = scoreValueArray[element]
}

Assigning value of an item in an array gives Bound value in a conditional binding must be an Optional type

I am getting a compile error saying
Bound value in a conditional binding must be an Optional type
Below is a screenshot of the code
You can convert the value of array[index] to an Optional doing something like this:
if let value = Int?(array[index]){
result += value
}
That's if your array contains Ints. You could also use AnyObject?, but you'll get a warning from xcode.
The array should be declared as Optional type, take Int?[] as an example,
let array:Int?[] = [nil, 2, 3]
let index = 0
let count = array.count
for index in 0..count {
if let value = array[index] {
println(value)
} else {
println("no value")
}
}
if the type of the value of array[index] is of optional, you could simple do like this:
if let value = array[index]{
result += value
}
In this case the compiler is complaining because array isn't a collection of Optional (nil-able) types. If it truly doesn't need to be, you don't actually need that if, since everything inside the array is guaranteed to be the same type, and that if statement won't protect you from a out-of-bounds error anyway. So just go with:
while ++index < length {
result += array[index]
}
or perhaps better:
for value in array {
result += value
}
or even better:
result = array.reduce(0) { $0 + $1 }