How to get the row index of 2D Array? - ios

I am new to Swift and I am using a 2D array for comparing and I need to get the row index once the condition is true but I got an error state that cannot invoke index with an argument list of type (of:Array<Float>)
My Code:
var entryCoordinate: [[Float]] = [[130.6,61.0],[167.5,61.0],[204.5,61.0],[243.6,61.0],[281.16,61.0],[315.3,61.0]]
for indexs in entryCoordinate
{
if indexs[0] == startPathPointX && indexs[1] == startPathPointY
{
let pathStartElement = indexs.index(of: indexs)
print(pathStartElement)
}
if indexs[0] == endPathPointX && indexs[1] == endPathPointY
{
let pathEndElement = indexs.index(of: indexs)
print(pathEndElement)
}
}

From your code with startPathPointY and endPathPointY you need to compare the second object from 2D array but you keep comparing the first one and you con use index(where:) with your array like this to get the pathStartElement and pathEndElement.
if let pathStartElement = entryCoordinate.index(where: { $0[0] == startPathPointX && $0[1] == startPathPointY }) {
print(pathStartElement)
}
if let pathEndElement = entryCoordinate.index(where: { $0[0] == endPathPointX && $0[1] == endPathPointY }) {
print(pathEndElement)
}

Try this code:
let myIndexPathStartElement = self.arrImagetData.index(where: { $0[0] == startPathPointX && $0[1] == startPathPointY })
let myIndexPathEndElement = self.arrImagetData.index(where: { $0[0] == endPathPointX && $0[1] == endPathPointY })

Related

Swift equivalent of this ActionScript function

I translated this tutorial on BSP into swift. In the tutorial there's this ActionScript function.
public function getRoom():Rectangle
{
// iterate all the way through these leafs to find a room, if one exists.
if (room != null)
return room;
else
{
var lRoom:Rectangle;
var rRoom:Rectangle;
if (leftChild != null)
{
lRoom = leftChild.getRoom();
}
if (rightChild != null)
{
rRoom = rightChild.getRoom();
}
if (lRoom == null && rRoom == null)
return null;
else if (rRoom == null)
return lRoom;
else if (lRoom == null)
return rRoom;
else if (FlxG.random() > .5)
return lRoom;
else
return rRoom;
}
}
I translated this function into Swift (to the best of my ability) I must have written it wrong because the function is returning a nil value when it shouldn't be.
My version in Swift:
// left/right child are initialized as follows:
// leftChild:Room?
// rightChild:Room?
public func getRoom() -> Room? {
if room != nil {
return room
} else {
var lRoom:Room?
var rRoom:Room?
if leftChild != nil {
lRoom = leftChild!.getRoom()!
}
if rightChild != nil {
rRoom = rightChild!.getRoom()!
}
if lRoom == nil && rRoom == nil {
return nil
} else if rRoom == nil {
return lRoom
} else if lRoom == nil {
return rRoom
} else if Double.random(in: 0..<1.0) > 0.5 {
return lRoom
} else {
return rRoom
}
}
}
Where Room is a basic class I made to help me handle the rooms.
class Room {
var x1:Int
var x2:Int
var y1:Int
var y2:Int
var center:CGPoint
init(X: Int, Y: Int, W: Int, H: Int) {
x1 = X
x2 = X + W
y1 = Y
y2 = Y + H
center = CGPoint(x: (x1 + x2) / 2, y: (y1 + y2) / 2)
}
}
I'm getting a nil value when I shouldn't be. I think I translated the function wrong. Rectangle would be CGRect in Swift but I replaced it with my Room class in other places in the code, so I know it'll work with the Room class here.
How would this function be written in Swift?
Your problem is that you are force unwrapping the result of getRoom - This function returns an optional and can legitimately return nil when your traversal hits a leaf node. Force unwrapping nil results in a crash
By using conditional unwrapping correctly you can not only make your code more readable, you can eliminate the crash.
public func getRoom() -> Room? {
if let _ = room {
return room
}
let lRoom = leftChild?.getRoom()
let rRoom = rightChild?.getRoom()
switch (lRoom != nil, rRoom != nil) {
case (false,false):
return nil
case (true,false):
return lRoom
case (false,true):
return rRoom
case (true,true):
return arc4random_uniform(2) == 1 ? lRoom: rRoom
}
}

swift - sort an array of objects by their optional boolean property without force unwrapping

I can sort this array of store objects by their 'flagship' boolean property, but how can I safely unwrap the 'flagship' property first?
let flagshipStores = self.stores.sort {
$0.flagship! && !$1.flagship!
}
let flagshipStores = self.stores.sort {
guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else { return false }
return flagship0 && !flagship1
}
One more approach: turn the Bool? into an Int, then compare the Ints. You get to specify how a nil value compares to non-nil values.
For instance, this sorts nil values before both false and true:
stores.sort { Int($0.flagship ?? -1) < Int($1.flagship ?? -1) }
This sorts nil values after both false and true:
stores.sort { Int($0.flagship ?? 2) < Int($1.flagship ?? 2) }
You can use the same pattern to make nil compare the same as true or the same as false. It's up to you.
Here's another approach.
You can use flatMap which will remove nil objects and unwrap those that are present. Then, the force unwrap will be safe to sort:
let flagshipStores = stores.flatMap({ return $0.flagship ? $0 : nil }).sort {
$0.flagship! && !$1.flagship!
}
This will remove stores with a nil flagship from the array.
How about:
$0.flagship == true && $1.flagship != true
The left side will succeed if the value is not nil and is true, the right side will succeed if the value is either nil or false.
As mr.Fixit pointed out on a comment, the accepted answer doesn't fully work because it doesn't take care of nils. Here is the correct answer with an extra string sample.
SWIFT 4
for a boolean sorting
let flagshipStores = self.stores.sorted(by: {
guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else {
if $0.flagship == nil && $1.flagship == nil || $0.flagship != nil && $1.flagship == nil{
return true
}
else {
return false
}
}
return ($0.flagship == $1.flagship || $0.flagship == true && $1.flagship == false ? true : false)
})
for strings comparison sorting
let stores = self.stores.sorted(by: {
guard let store0 = $0.store, let store1 = $1.store else {
if $0.store == nil && $1.store == nil || $0.store != nil && $1.store == nil{
return true
}
else {
return false
}
}
return ( ($0.store)?.localizedStandardCompare($1.store!) == ComparisonResult.orderedAscending )
})
To filter nil values just use compactMap before sort
let flagshipStores = self.stores.compactMap { return $0.flagship }.sorted {
$0 && !$1
}
You could use this function to compare the Optional values without the need to unwrap.
func sortOptionalValues<T: Comparable>(lhs: T?, rhs: T?) -> Bool? {
switch (lhs != nil, rhs != nil) {
case (false, false):
return nil
case (true, false):
return true
case (false, true):
return false
case (true, true):
guard let lhs = lhs, let rhs = rhs else { return nil }
return lhs < rhs
}
}

swift multiple conditions if statement with && operation [duplicate]

This question already has answers here:
Checking if text fields are empty cause error in Swift 2
(2 answers)
Closed 6 years ago.
I have 4 text boxes.I don't want to allow user to let all these 4 textfields empty. How can I check multiple conditions in swift. I did like this but it's giving me an error
if self.txtIncomeAd.text?.isEmpty && self.txtIncomeRec.text?.isEmpty &&
like wise. What is the correct way I can do this?
Please help me.
Thanks
you can simply use isEmpty property.
if !self.textFieldOne.text!.isEmpty && !self.textFieldTwo.text!.isEmpty && !self.textFieldThree.text!.isEmpty && !self.textFieldFour.text!.isEmpty {
...
}
or you can also safely unwrap the text value and the check that it is empty of not
if let text1 = self.textFieldOne.text, text2 = self.textFieldTwo.text, text3 = self.textFieldthree.text,text4 = self.textFieldFour.text where !text1.isEmpty && !text2.isEmpty && !text3.isEmpty && !text4.isEmpty {
...
}
Or you can compare with Empty "" String
if self.textFieldOne.text != "" && self.textFieldTwo.text != "" && self.textFieldThree.text != "" && self.textFieldFour.text != "" {
...
}
and we can also do this with Guard
guard let text = self.myTextField.text where !text.isEmpty else {
return
}
if !self.txtIncomeAd.text!.isEmpty && !self.txtIncomeRec.text!.isEmpty && !self.txtIncomeAd.text!.isEmpty && !self.txtIncomeRec.text!.isEmpty
{
...
}
It gives you an error because the text in the textField is optional. First you have to unwrap them all.
if let txtIncomeAd = self.txtIncomeAd.text,
let txtIncomeRec = self.txtIncomeRec.text {
if txtIncomeAd.isEmpty && txtIncomeRec.isEmpty {
// Do Something
}
} else {
// Empty text field
}
You can check with isEmpty boolean property.
if ((inputTextField.text?.isEmpty) != nil && (inputTextField1.text?.isEmpty)!= nil && (inputTextField2.text?.isEmpty)!=nil) {
}
or
if ((inputTextField.text?.isEmpty)! && (inputTextField1.text?.isEmpty)! && (inputTextField2.text?.isEmpty)!) {
}
Here's something a bit different:
extension UILabel {
var textIsEmpty: Bool { return text?.isEmpty ?? true }
}
class MyClass: UIView {
let txtIncomeAd = UILabel()
let txtIncomeRec = UILabel()
var textFieldsAreNonEmpty: Bool {
return ![txtIncomeAd, txtIncomeRec].contains { $0.textIsEmpty }
}
}
let c = MyClass()
c.txtIncomeAd.text = "hello"
c.txtIncomeRec.text = "there"
if c.textFieldsAreNonEmpty {
print("text fields are valid")
}

Random array string getting nil

I am using the random range function to my array string. Also I am using a filter to not repeat to my array string, but sometimes my first random string is nil.
Random range code:
func randomNumber(range: Range<Int> = 1...6) -> Int {
let min = range.startIndex
let max = range.endIndex
return Int(arc4random_uniform(UInt32(max - min))) + min
}
I'm getting nil from the firstItem:
var a = cities[randomNumber(0...80)]
if Marmara.contains(a){
firstItem = a
print(firstItem) //It's getting nil sometimes.
var filteredForSecond = Marmara.filter{$0 != firstItem}
secondItem = filteredForSecond[randomNumber(0...filteredForSecond.count-1)]
print(secondItem)
var filteredForThird = Marmara.filter{$0 != secondItem && $0 != firstItem}
thirdItem = filteredForThird[randomNumber(0...filteredForThird.count-1)]
print(thirdItem)
var filteredForFourth = Marmara.filter{$0 != thirdItem && $0 != secondItem && $0 != firstItem}
print(fourthItem)
fourthItem = filteredForFourth[randomNumber(0...filteredForFourth.count-1)]
//sehirler.removeAtIndex(s)
print("\(firstItem), \(secondItem), \(thirdItem), \(fourthItem)")
}
I have an "81" string in the array using this code. What should I do to fix this nil string problem?
I would at least make the following change. See if this fixes the problem.
var a = cities[randomNumber(0...cities.count-1)]
I solved the problem. I'm checking if it is nil, taking again random string and it's not getting nil anymore.
Here is the working code:
var a = cities[randomNumber(0...cities.count-1)]
while a.isEmpty{
a = cities[randomNumber(0...cities.count-1)]
}
if Marmara.contains(a) && a != ""{
firstItem = a
if firstItem.isEmpty{
print("nil")
}
print(firstItem)
var filteredForSecond = Marmara.filter{$0 != firstItem}
secondItem = filteredForSecond[randomNumber(0...filteredForSecond.count-1)]
print(secondItem)
var filteredForThird = Marmara.filter{$0 != secondItem && $0 != firstItem}
thirdItem = filteredForThird[randomNumber(0...filteredForThird.count-1)]
print(thirdItem)
var filteredForFourth = Marmara.filter{$0 != thirdItem && $0 != secondItem && $0 != firstItem}
print(fourthItem)
fourthItem = filteredForFourth[randomNumber(0...filteredForFourth.count-1)]
//sehirler.removeAtIndex(s)
print("\(firstItem), \(secondItem), \(thirdItem), \(fourthItem)")
}

Stuck in a loop. Very strange because the code sometimes work and sometimes just freezes

I am writing a puzzle game for an IOS. In my code I need to fill an array with some random (and non-random numbers) that will represent the main data structure.
func Random(r : Range<Int>) -> Int {
return Int(arc4random_uniform(UInt32(r.endIndex - r.startIndex))) + r.startIndex
} // function to generate random number
var arrWithColors = [Int]() // array that will hold the numbers
//function to that check if an array contains a number in a range already
func checkForNumberInArrayWithRange(r: Range <Int>, n: Int ) -> Bool {
for i in r.startIndex..<r.endIndex {
if arrWithColors[i] == n { return true }
}
return false
}
// here is the main function where i keep getting stuck. Out of let's say five times it would only work 3 or even less.
func randHexWithTag() {
var rNumber : Int = Random(0...5)
for i in 0...5 {
while (true) {
rNumber = Random(0...5)
if !checkForNumberInArrayWithRange(0...5, n: rNumber) {
break
}
}
arrWithColors[i] = rNumber
}
arrWithColors[10] = arrWithColors[1]
for i in 6...11 {
while(true) {
rNumber = Random(0...5)
if ((rNumber == arrWithColors[0] && i == 9) || (rNumber == arrWithColors[2] && i == 11)) {
continue
}
if !checkForNumberInArrayWithRange(6...11, n: rNumber) {
break
}
}
if (i != 10) {
arrWithColors[i] = rNumber
}
}
arrWithColors[13] = arrWithColors[4]
for i in 12...17 {
while(true) {
rNumber = Random(0...5)
if (rNumber == arrWithColors[3] && i == 12) || (rNumber == arrWithColors[5] && i == 14) {
continue
}
if !checkForNumberInArrayWithRange(12...17, n: rNumber) {
break
}
}
if (i != 13) {
arrWithColors[i] = rNumber
}
}
}
The above code will ALWAYS fail during the first call to checkForNumberInArrayWithRange on this line:
if arrWithColors[i] == n { return true }
That is because arrWithColors is empty, and index i is out of range

Resources