swift optional array subscripts - arrays

Simple playground code like below:
var array :[Int?]
array = [1, 2, 3]
array![1] = 4
Got an error from Playground
Playground execution failed: error: :8:1: error: '#lvalue $T6' is not identical to 'Int?'
array![1] = 4
Any suggestion guy?

You are defining a non-optional array of optional Ints. When you try to access it you are trying to force unwrap the array itself which is not necessary. You can simply do:
array[1] = 4
An optional array of non-optional Int would look like this:
var array: [Int]?

OK, I got the answer by myself
var array :[Int]?
array = [1, 2, 3]
if var tmpArray = array {
tmpArray[1] = 4
array = tmpArray
}
How could I say this, Cons&Pros

Related

How to find repeated values in multidimensional array in angularjs

var arrayValues = [[2,3,5],[3,5]]
var commonArrayValues = _.intersection(arrayValues);
Currently it is working as,
_.intersection([[2,3,5],[3,5]])
Result: [2,3,5]
But it should work as, (i.e outer array should be removed)
_.intersection([2,3,5],[3,5])
Expected Result: [3,5]
Anyone kindly give me a proper solutions. Thank you in advance.
You can use apply with intersection to get what you want:
var result = _.intersection.apply(null, arrayValues);
var arrayValues = [[2,3,5],[3,5], [2,3,5,6]]
var result = _.intersection.apply(null, arrayValues);
document.getElementById('results').textContent = JSON.stringify(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore.js"></script>
<pre id="results"></pre>
intersection *_.intersection(arrays)
Computes the list of values that are the intersection of all the arrays. Each value in the
result is present in each of the arrays.
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
var arrayValues = [[2,3,5],[3,5]]
Here arrayValues is an array having 2 arrays. Where as _.intersection expects arrays as parameter and not an array having arrays.
_.intersection([2,3,5],[3,5])
Or
_.intersection(arrayValues[0],arrayValues[1])
will output as what you need.
The only way I can think of is using eval:
var arrayValues = [[2,3,5],[3,5]]
var evalString = '_.intersection(';
arrayValues.forEach(function (element, index){
evalString += 'arrayValues['+index+'],';
});
evalString =evalString.slice(0, -1);
evalString += ');'
eval(evalString);
evalString would end being something like _.intersection(arrayValues[0],arrayValues[1],...,arrayValues[n]);

How to declare the array type in swift

So in a swift playground file, I am trying to execute the following closure:
var list = [5, 4, 3]
var Arraymultiplier = {(list:Array) -> Array in
for value in list {
value*2
return list
}
}
Arraymultiplier(list)
When I do this though, I get an error saying that the generic type Array must be referenced in <..> brackets, but when I put the brackets, I get another error.
What's the right way to declare the array type as an input and a return?
Array is a generic type, meaning that it expects to see the actual type of the members of the array to be specified within < > immediately following Array:
var arrayMultiplier = {(list: Array<Int>) -> Array<Int> in
// do whatever you want here
}
Or, in the case of arrays, there is a convenient syntax that uses the [ ] characters and omits the need for Array reference at all:
var arrayMultiplier = {(list: [Int]) -> [Int] in
// do whatever you want here
}
I'm not sure what the original code sample was trying to do, but it looks like you might have been trying to build a new array with each item multiplied by 2. If so, then you might do something like:
let inputList = [5, 4, 3]
let arrayMultiplier = { (list: [Int]) -> [Int] in
var results = [Int]() // instantiate a new blank array of `Int`
for value in list { // iterate through array passed to us
results.append(value * 2) // multiply each `value` by `2` and add it to the `results`
}
return results // return results
}
let outputList = arrayMultiplier(inputList)
Or, obviously, you could efficiently achieve similar behavior using the map function:
let outputList = inputList.map { $0 * 2 }

Populate Array with a set of Strings from a for-in loop for Swift

I am kinda stumped on figuring this out. I want to populate an array with the string values that comes from a for-in loop.
Here's an example.
let names = ["Anna", "Alex", "Brian", "Jack"]
for x in names {
println(x)
}
The current x value would generate 4 string values (Anna, Alex, Brian, Jack).
However I need some advice in going about getting these four values back into an array. Thank you in advance.
Whatever is on the right side of a for - in expression must be a SequenceType. Array, as it happens, can be initialised with any SequenceType. So if you're just doing something like this:
var newArray: [String] = []
for value in exoticSequence {
newArray.append(value)
}
The same thing can be accomplished (faster), by doing this:
let newArray = Array(exoticSequence)
And it doesn't matter what type exoticSequence is: if the for-in loop worked, Array() will work.
However, if you're applying some kind of transformation to your exoticSequence, or you need some kind of side effect, .map() might be the way to go. .map() over any SequenceType can return an array. Again, this is faster, and more clear:
let exoticSequence = [1, 2, 3]
let newArray = exoticSequence.map {
value -> Int in
// You can put whatever would have been in your for-in loop here
print(value)
// In a way, the return statement will replace the append function
let whatYouWouldHaveAppended = value * 2
return whatYouWouldHaveAppended
}
newArray // [2, 4, 6]
And it's equivalent to:
let exoticSequence = [1, 2, 3]
var newArray: [Int] = []
for value in exoticSequence {
print(value)
let whatYouWouldHaveAppended = value * 2
newArray.append(whatYouWouldHaveAppended)
}
newArray // [2, 4, 6]

swift getting an array from something like array[0..<10]

I want to get a range of objects from an array. Something like this:
var array = [1,3,9,6,3,4,7,4,9]
var newArray = array[1...3] //[3,9,6]
The above would access elements from index 1 to 3.
Also this:
newArray = array[1,5,3] // [3,4,6] would be cool
This would retrieve elements from index 1, 5 and 3 respectively.
That last example can be achieved using PermutationGenerator:
let array = [1,3,9,6,3,4,7,4,9]
let perms = PermutationGenerator(elements: array, indices: [1,5,3])
// perms is now a sequence of the values in array at indices 1, 5 and 3:
for x in perms {
// iterate over x = 3, 4 and 6
}
If you really need an array (just the sequence may be enough for your purposes) you can pass it into Array's init method that takes a sequence:
let newArray = Array(perms)
// newArray is now [3, 4, 6]
For your first example - with arrays, that will work as-is. But it looks from your comments like you're trying it with strings as well. Strings in Swift are not random-access (for reasons relating to unicode). So you can't use integers, they have an String-specific bidirectional index type:
let s = "Hello, I must be going"
if let i = find(s, "I") {
// prints "I must be going"
println(s[i..<s.endIndex])
}
This works :
var n = 4
var newArray = array[0..<n]
In any case in
Slicing Arrays in Swift you'll find a very nice sample of the Python slice using a extension to Arrays in Swift.

swift: modifying arrays inside dictionaries

How can I easily add elements to an array inside a dictionary?
It's always complaining with could not find member 'append' or could not find an overload for '+='
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
// all of these fail
dict["key"] += 4
dict["key"].append(4) // xcode suggests dict["key"].?.append(4) which also fails
dict["key"]!.append(4)
dict["key"]?.append(4)
// however, I can do this:
var arr = dict["key"]!
arr.append(4) // this alone doesn't affect dict because it's a value type (and was copied)
dict["key"] = arr
if I just assign the array to a var, modify it and then reassign it to the dict, won't I be copying everything? that wouldn't be efficient nor elegant.
Swift beta 5 has added this functionality, and you've nailed the new method in a couple of your attempts. The unwrapping operators ! and ? now pass through the value to either operators or method calls. That is to say, you can add to that array in any of these ways:
dict["key"]! += [4]
dict["key"]!.append(4)
dict["key"]?.append(4)
As always, be careful about which operator you use -- force unwrapping a value that isn't in your dictionary will give you a runtime error:
dict["no-key"]! += [5] // CRASH!
Whereas using optional chaining will fail silently:
dict["no-key"]?.append(5) // Did it work? Swift won't tell you...
Ideally you'd be able to use the new null coalescing operator ?? to address this second case, but right now that's not working.
Answer from pre-Swift beta 5:
It's a quirk of Swift that it's not possible to do what you're trying to do. The issue is that the value of any Optional variable is in fact a constant -- even when forcibly unwrapping. If we just define an Optional array, here's what we can and can't do:
var arr: Array<Int>? = [1, 2, 3]
arr[0] = 5
// doesn't work: you can't subscript an optional variable
arr![0] = 5
// doesn't work: constant arrays don't allow changing contents
arr += 4
// doesn't work: you can't append to an optional variable
arr! += 4
arr!.append(4)
// these don't work: constant arrays can't have their length changed
The reason you're having trouble with the dictionary is that subscripting a dictionary returns an Optional value, since there's no guarantee that the dictionary will have that key. Therefore, an array in a dictionary has the same behavior as the Optional array, above:
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
dict["key"][0] = 5 // doesn't work
dict["key"]![0] = 5 // doesn't work
dict["key"] += 4 // uh uh
dict["key"]! += 4 // still no
dict["key"]!.append(4) // nope
If you need to change something in an array in the dictionary you'll need to get a copy of the array, change it, and reassign, like this:
if var arr = dict["key"] {
arr.append(4)
dict["key"] = arr
}
ETA: Same technique works in Swift beta 3, though constant arrays no longer allow changes to contents.
The accepted answer bypasses the following much simpler possibility, which also works for older Swift versions:
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
print(dict)
dict["key", default: [Int]()].append(4)
print(dict)
This will print:
["key": [1, 2, 3]]
["key": [1, 2, 3, 4]]
And this:
var dict = Dictionary<String, Array<Int>>()
dict["key", default: [Int]()].append(4)
print(dict)
will print:
["key": [4]]
As a simple workaround you can use a NSMutableArray:
import Foundation
var dict = Dictionary<String, NSMutableArray>()
dict["key"] = [1, 2, 3] as NSMutableArray
dict["key"]!.addObject(4)
I am using effectively such simple solution in my project:
https://github.com/gui-dos/Guigna/blob/5c02f7e70c8ee3b2265f6916c6cbbe5cd3963fb5/Guigna-Swift/Guigna/GuignaAppDelegate.swift#L1150-L1157
Here is what I was telling Nate Cook, in the comments for his quality answer. This is what I consider "easily [adding] elements to an array inside a dictionary":
dict["key"] = dict["key"]! + 4
dict["key"] = dict["key"] ? dict["key"]! + 4 : [4]
For now, we need to define the + operator ourselves.
#infix func +<T>(array: T[], element: T) -> T[] {
var copy = array
copy += element
return copy
}
I think this version removes too much safety; maybe define it with a compound operator?
#infix func +<T>(array: T[]?, element: T) -> T[] {
return array ? array! + element : [element]
}
dict["key"] = dict["key"] + 4
Finally, this is the cleanest I can get it, but I'm confused about how array values/references work in this example.
#assignment func +=<T>(inout array: T[]?, element: T) {
array = array + element
}
dict["key"] += 5
Use 'for in', for getting values from dictionary's inside array. Here's an example to help you
var a = ["x":["a","b","c"], "y":["d"]]
for b in a {
print(b)
}
Output:
("x", ["d"])
("y", ["a", "b", "c"])

Resources