suffix array Index out of bounds - swift

I have an array , when I suffix array and want to select element , I get error: Index out of bounds.
But when I prefix array and select element, It's sucess.
How should I do that I can select after suffix array?
Here is code:
let array = [1,2,3,4,5,6,7,8,9,10]
let suffixArray = array.suffix(5)//[6,7,8,9,10]
let prefixArray = array.prefix(5)//[1,2,3,4,5]
print(suffixArray[2])//Index out of bounds
print(prefixArray[2])//sucess print "3"

The problem you are having is that with .suffix the array does not start with 0. So if you wanted to print the 3rd number in the suffix array, you would have to call print(suffixArray[7].
If you read the description for the return value here. It reads:
A subsequence terminating at the end of the collection with at most maxLength elements.
And if you read the description to subsequence:
A collection representing a contiguous subrange of this collection’s elements. The subsequence shares indices with the original collection.
Full example for playground:
let array = [1,2,3,4,5,6,7,8,9,10]
let suffixArray = array.suffix(5) // [6,7,8,9,10]
let prefixArray = array.prefix(5) // [1,2,3,4,5]
var newSuffixArray: [Int] = []
for i in suffixArray {
newSuffixArray.append(i)
}
print(suffixArray[7]) // 8
print(newSuffixArray[2]) // 8
print(prefixArray[2]) // 3

Both prefix and suffix return an ArraySlice rather than another Array.
Here's an excerpt from the ArraySlice documentation:
Unlike Array and ContiguousArray, the starting index for an
ArraySlice instance isn’t always zero. Slices maintain the same
indices of the larger array for the same elements, so the starting
index of a slice depends on how it was created, letting you perform
index-based operations on either a full array or a slice. Sharing
indices between collections and their subsequences is an important
part of the design of Swift’s collection algorithms.
You can see that by looking into the indices property of prefixArray and suffixArray.
Generally you are encouraged to use methods of accessing elements that collections provide instead of assuming values of indices.

Related

Get position as int from Set<>.index in Swift

I have a set collection and I want to get index of an element. I'm using firstIndex function of set but It returns Set.index. How can I convert it to int?
let index = mySet.firstIndex(of: dataSource) // This returns Set<>.index
Set.index Documentation
Set is unordered, try using an Array for example
It is very easy to convert a set index to an int
index.hashValue
however you will find that that index isn't very useful
Set(["a", "b", "c"]).firstIndex(of: "a")?.hashValue
// 5346078814578125500
this is because a set uses a hash table as its underlying storage mechanism. You'll see this if you try to print the index itself
Index(_variant: Swift.Set<Swift.String>.Index._Variant.native(Swift._HashTable.Index(bucket: Swift._HashTable.Bucket(offset: 3), age: -233657665)))
What firstIndex returns to you is simply the hashkey at which that element is stored. It does not relate to any kind of "position" because hash tables don't have a meaningful sense of position.

Swift: Get max value for key in array of dictionaries

I have an array containing dictionaries.
let arr = [["test":1], ["test":2], ["test":3], ["test":4]]
I now need to get the one dictionary that contains the highest value for the key "test" (without iterating through everything). I was thinking about filter(_:) but this will only filter out. map(_:) also does not work as I need to filter and not to map.
There's an example how to get the key with the highest value in a dictionary but this does not work in this case.
let hues = ["Heliotrope": 296, "Coral": 16, "Aquamarine": 156]
let greatestHue = hues.max { a, b in a.value < b.value }
print(greatestHue)
Any help is appreciated!
You can use max much like in your example.
let arr = [["test":1], ["test":4], ["test":3], ["test":2]]
print(arr.max { $0["test"]! < $1["test"]! })
This gives the dictionary with the highest value.
Of course the use of ! is bad unless it is guaranteed that each dictionary really has a "text" key.
Also note that using max will still result in the entire array being iterated. You can't avoid that unless your dictionaries are always sorted by the value. Then in that case simply use last instead of max.

Swift adding to end of array

I know that Array has the append(_:) method, but this mutates the original array.
Why doesn't Array also implement appending(_:) which would return a new array with that element appended? I've implemented this a few times now, but am wondering if there is a reason why it doesn't already exist?
(My only guess would be that this is to do with efficiency - if you used this method in a loop you would be copying your array multiple times?)
You can make an extension of Array do to this :
extension Array{
func appending(_ element:Element) -> Array<Element>{
var result = self
result.append(element)
return result
}
}
What are we discussing?
Starting from 'append' documentation:
/// Append `newElement` to the Array.
///
/// - Complexity: Amortized O(1) unless `self`'s storage is shared with another live array; O(`count`) if `self` does not wrap a bridged
NSArray; otherwise the efficiency is unspecified..
public mutating func append(newElement: Element)
You need to have knowledge about pointer and smart pointer.
M elements
var a = [1, 2, 3]
Is a simple array.
If you append N elements, complexity will be O(N)
func addElements() {
for elment in [4, 5, 6] {
a.append(element)
}
}
If you create a new array starting from a:
var b = a
At run time b points to a, so if you execute again addElements complexity will be O(M) in order to copy original array plus O(N) in order to add N elements.
Why documentation says?
"otherwise the efficiency is unspecified.."
Because in this example we have a simple array of integer, but the behaviour of copying array of custom objects is unpredictable.

How to compare Range<String.Index> and DefaultBidirectionalIndices<String.CharacterView>?

This comparison worked in Swift 2 but doesn't anymore in Swift 3:
let myStringContainsOnlyOneCharacter = mySting.rangeOfComposedCharacterSequence(at: myString.startIndex) == mySting.characters.indices
How do I compare Range and DefaultBidirectionalIndices?
From SE-0065 – A New Model for Collections and Indices
In Swift 2, collection.indices returned a Range<Index>, but because a range is a simple pair of indices and indices can no longer be advanced on their own, Range<Index> is no longer iterable.
In order to keep code like the above working, Collection has acquired an associated Indices type that is always iterable, ...
Since rangeOfComposedCharacterSequence returns a range of
character indices, the solution is not to use indices, but
startIndex..<endIndex:
myString.rangeOfComposedCharacterSequence(at: myString.startIndex)
== myString.startIndex..<myString.endIndex
As far as I know, String nor String.CharacterView does not have a concise method returning Range<String.Index> or something comparable to it.
You may need to create a Range explicitly with range operator:
let myStringContainsOnlyOneCharacter = myString.rangeOfComposedCharacterSequence(at: myString.startIndex)
== myString.startIndex..<myString.endIndex
Or compare only upper bound, in your case:
let onlyOne = myString.rangeOfComposedCharacterSequence(at: myString.startIndex).upperBound
== myString.endIndex

Fatal Error: Array Index out of range in Swift Xcode6

I keep getting this error in my func
I'm trying to read the value in array answerRecord. I uses a global var arrayCount, which keep track which index im currently pointing to.
func buttonColourControl(){
switch answerRecord[arrayCount]{
case1: xxxxxxx
I did a println in my earlier func and it return a value of int 1 for the var arrayCount
Therefore arrayCount is not empty. So it should be able to interpret the array as:
*assuming arrayCount is now 1
answerRecord[arrayCount] should be interpreted as answerRecord[1]
Please correct me if im wrong
#IBAction func nextButtonClicked(sender: UIButton) {
arrayCount = ++arrayCount
question.text = spouseQuesion[arrayCount]
controlBackNextButton()
answer1Label.text = spouseAnswer1[arrayCount]
answer2Label.text = spouseAnswer2[arrayCount]
answer3Label.text = spouseAnswer3[arrayCount]
println(arrayCount)
buttonColourControl()
}
Let's say you have an array with one object in it:
let arr = ["hello"]
The only valid index into that array is 0. arr[0] is legal. arr[1] is not. The array has 1 element but its index number is 0.
This is true for any array. Every array holds some number of elements. It might be 0 elements, in which case no index is legal. It might be 3 elements, in which case you can refer to the array's elements by index numbers 0, 1, and 2. And so on. That's all. Those are the rules. You cannot use any other index number or you will crash.
So the error message is simply telling you that you are making that mistake. You have an array answerRecord and it has some number of elements - I have no idea how many, and it doesn't matter. Then you are using the expression answerRecord[arrayCount] and the value of arrayCount is outside the bounds I have just explained. That's all you need to know. The error message tells you the bug in your program. Now you can fix it.