Very Basic Misunderstanding of for loops in Swift - swift

I'm new to swift. can someone please explain what I'm doing wrong here.
1.
var numbers = [1, 5, 7, 6, 6, 6, 6, 6, 2]
for i in numbers{
print(numbers[i],terminator: "")
}
why doesn't this just print the numbers in the array?
2.
Here I want to set the elements in the array to a random number from 0 to 2, and then print them.
for j in numbers{
numbers[j] = Int.random(in: 0...2)
print(numbers[j],terminator: "")
}
this seems to work, but then if, outside of the for loop, I print them again:
for k in numbers{
print(numbers[k],terminator: "")
}
It outputs different numbers, from 0 to 2
3.
OK so I try a different syntax:
for m in numbers{
print(m,terminator: "")
}
now I get the same numbers every time and they are not from 0 to 2... I'm sure my mistakes are trivial but an explanation would help me out. Thanks.

to achieve what you expect, you need to loop over the indices of the array, like this:
var numbers = [1, 5, 7, 6, 6, 6, 6, 6, 2]
for i in numbers.indices { // <-- here
print(numbers[i])
}
And as mentioned, read the basics of Swift.

Related

Trying to access some elements in an IndexSet

I'm using IndexSet and I'm trying to access some indexes which at times are consecutive and at other times are not.
For example, my set may contain [1, 2, 3, 5, 6, 7, 13, 31]
I want to pull out of the set a range of 3...13, but am having difficulty with the syntax. I've learned how to use the function commands from Apple documentation, by using myIndexSet.sorted(). However, the Apple Documentation does not give an example of how to access a range of elements in the set. The Apple Documentation for accessing elements in the index set are the following:
subscript(Range<IndexSet.Index>)
I've tried a number of ways to write this but can't figure out how to do it right. Can someone show me how to access a range of elements in the set to create a new set? I've tried things such as:
let subset = subscript(Range: myLargerSet.3...13)
but it doesn't seem to work.
Thanks
What you're looking for is the intersection of your IndexSet ([1, 2, 3, 5, 6, 7, 13, 31]) with another IndexSet ([3, 4, ..., 12, 13]):
let yourIndexSet: IndexSet = [1, 2, 3, 5, 6, 7, 13, 31]
let desiredIndexRange = IndexSet(3...13)
let indicesOfInterest = yourIndexSet.intersection(desiredIndexRange)
print(indicesOfInterest.sorted()) // => [3, 5, 6, 7, 13]
One possible solution is to use a filter to create a new IndexSet.
let set = IndexSet(arrayLiteral: 1,2,3,5,6,7,13,31)
let subset = set.filteredIndexSet { (index) -> Bool in
index >= 3 && index <= 13
}
You can access a slice of your original set as follows:
let slice = indexSet[indexSet.indexRange(in: 3...13)]
slice accesses the existing elements in place, so creation of the slice is O(1)

Swift: Working with for and array

I started to learn Swift but I have some problems like I want to sum two arrays and put them in a third array and I have to do it with for loop.
var ar1 = [1,3,5,7,9]
var ar2 = [2,4,6,8,10]
var ar3 : [Int] = [5]
for i in 0... ar1.count-1 {
// for loop for index
ar3[i] = ar1[i] + ar2[i]
}
But I get an out of range error. I tried a lot but I could not solve it.
Your code looks more like C or Java than swift, but you're on the right track. There are many other ways to do this, but this code is very similar to what you were trying to do:
func example() {
let array1 = [1, 3, 5, 7, 9]
let array2 = [2, 4, 6, 8, 10]
var array3 = [Int]()
for i in 0 ..< array1.count {
array3.append(array1[i] + array2[i])
}
for element in array3 {
print("\(element)")
}
}
Use "let" if the variable never changes once you defined it.
I added a loop at the bottom so you can verify the results, and also so you can see that you don't need "i" in loops.

Index out of range in Swift with removeAtIndex

I tried to remove an element in NSUserDefaults which is the same as stockSymbol's value when click a button. My idea is that cast the NSUserDefaults to an array and remove the element with removeAtIndex. Here is my code.
#IBAction func buttonFilledStarClicked(sender: AnyObject) {
NSLog("Filled star clicked")
self.buttonFilledStar.hidden = true
self.buttonEmptyStar.hidden = false
var Array = NSUserDefaults.standardUserDefaults().objectForKey("favorites")! as! [String]
var countArray = (NSUserDefaults.standardUserDefaults().objectForKey("favorites")! as! [String]).count - 1
for i in 0...countArray {
if stockSymbol! == Array[i] {
NSLog("i is : \(i)")
Array.removeAtIndex(i)
}
else {}
}
NSLog("Array is: \(Array), countArray is: \(countArray)")
}
However it has 'out of index' error.
It works when I just comment Array.removeAtIndex(i) out.
Array looks like this --
["aa", "bb", "Test!", "Test!"]
Any suggestions? Thank you in advance.
So, the change you can make to resolve the error with the least impact on your code overall would be to simply iterate through the indices backwards:
for i in (0...countArray).reverse() {
if stockSymbol! == Array[i] {
NSLog("i is : \(i)")
Array.removeAtIndex(i)
}
else {}
}
But the best option is to just use Swift's filter:
Array = Array.filter { $0 != stockSymbol }
An expanded note on why the crash is happening...
Let's take a simplified example. Say I have the following array:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
And I want to remove all of the odd numbers out of it. Using your first naïve approach, I might write my logic like this:
for i in 0..<arr.count {
if arr[i] % 2 != 0 {
arr.removeAtIndex(i)
}
}
Look at what happens on each iteration.
On the first iteration, we have arr[i] of 1. This is an odd number, so we'll removeAtIndex, and our array now actually looks like this:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
The array's size is now smaller--it has just 9 elements. But the loop doesn't work like an old C-style for loop where i < arr.count is checked on each iteration (which is part of why this loop is faster).
But notice something else that happens when we iterate forward...
On the second iteration, i is equal to 1, and so what does arr[i] give us? It gives us 3. We never even check 2. On the first iteration, when i was 0, it was at index 1. On the second iteration, when i is 1, the 2 is at index 0.
So on the second iteration, we'll call removeAtIndex with i equal to 1 and remove the 3.
This pattern will continue for a few iterations until we end up with our array of just even numbers:
[2, 4, 6, 8, 10]
But this happens after the iteration where i was equal to 4, and the loop is going to try running until i is equal to 10.
On the sixth iteration of the loop, we try to access the element at index 5 of the array. But the array only has five elements, so the largest index is 4. When we try to access index 5, we crash.
You should not remove it from inside of the loop, when you call removeAtIndex(i) Array removes the item so you have 1 less item then countArray.. so you have to have another array to remember which item you want to remove and remove it outside of the loop.. or better option is to use filter
// Filter only strings that match stockSymbol
Array = Array.filter { $0 == stockSymbol! }
Try to find out which i that give you index out of range result. Is it the 0 or the last one. Maybe you will find some other useful clue.
First of all Array is a type, maybe you can call:
var favourites = NSUserDefaults.standardUserDefaults().objectForKey("favorites")! as! [String]
Then you don't need a array's count variable you can access using count arrays property.
Finally if you are iterating through an array and remove an element it always going to throw "index's error" because the index is not the same as the beginning..
For solving this you can take two pointers of the index variable, but what I would do is something like this:
var correctElements = favourites.filter({$0!=stockSymbol})

How to add integer to array (with explicite int index) in swift?

I read swift handbook and was trying to do some exercises. But I run into a problem and I do not know if I do something wrong or if xCode 6 beta is just buggy.
// Playground - noun: a place where people can play
import Cocoa
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var lastLargest = Integer[]()
var index = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
//lastLargest[index] = number
index++
largest = number
}
}
}
index
lastLargest
largest
As soon as I uncomment lastLargest[index] = number I do not get any results on right side in playground. Nor I get any infos about index, lastLargest or largest.
Following example does not work either:
var index2 = 0
var lastLargest2 = Integer[]()
lastLargest2[index2] = 1
index2++
lastLargest2[index2] = 2
You are appending using an out of bound array-index. Don't do that. Instead, use append:
lastLargest.append(number)
From Apple's documentation:
You can’t use subscript syntax to append a new item to the end of an array. If you try to use subscript syntax to retrieve or set a value for an index that is outside of an array’s existing bounds, you will trigger a runtime error.
When you're using explicit indexes (subscript notation) to set values in a mutable array, some value must already exist in that array at that index. When you use subscript notation, you're essentially using a 'set', rather than a 'set and add if necessary'.
As a result, you should be using:
lastLargest.insert(number, atIndex: index)
If you want to insert a new item. This will let you insert an item at the specified index, assuming your collection's size is already greater than or equal to the index you're trying to replace.

Matlab -- Finding missing number in a list

I have a relatively large data set, and I'm looking for the missing number via MatLab.
For example, I have a list of numbers that might look like:
1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 9, 10, 10.....
You can see the 8 is missing here. The list is in the thousands, and there are maybe just a couple missing numbers. How can I find out which ones are missing? My search only turned up useful results without randomly repeating numbers. Seems simple but I can't figure it out.
Thanks for help!
Use unique, like this:
B=unique(A); % A is your data
C=setdiff(1:max(A),B)
and C is your desired missing numbers.
EDIT (afetr seeing claj's answer):
If your data starts from another value (not "1"), the second line should be:
C=setdiff(min(A):max(A),B)
EDIT2: (according to Eitan's comment)
C=setdiff(min(A):max(A),A);
This line replaces the two lines from the original answer.
You could do something like this:
% Your data:
data = [1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 9, 10, 10];
for i = 1:data(end)
if (isempty(find(data==i)))
disp(['i = ',num2str(i)]);
end
end
Which will print out the values of the missing elements.
Or even simpler you could just use the ismember() function to construct
the set difference in just a single line below.
% First enter your data and construct 'set':
data = [1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 9, 10, 10];
set = data(1):data(end);
Then to determine which elements of 'set' are also in 'data':
ismember(set, data)
The output then shows the locations in 'set' where the data is missing:
ans =
1 1 1 1 1 1 1 0 1 1
Use the ismember() function to check if a number is member of the data array
% set your data array
maximum = max(data);
minimum = min(data);
for i= minimum:maximum
if ~ismember(i,data);
disp([num2str(i) , ' is missed']);
end
end
Create a unique list of values in the array.
Find the min and max numbers in this unique set (these should be the same numbers as in the array, but quicker to find).
Create a range from min to max like [min:max].
Make a set difference of the uniqued array and the range-set.
This gives you the missing numbers in decently quick way.
this is similar to a few of the above but the simplest i've found is
find(~ismember(set,data))
which will return the indices of the members of set that are not in data