Checking if array value is valid number in Swift 4 - objective-c

I have following code which is working in Objective-C:
NSScanner *scanner ;
for(int i = 0; i < [expression count]; i = i + 2)
{
scanner = [NSScanner scannerWithString:[expression objectAtIndex:i]];
BOOL isNumeric = [scanner scanInteger:NULL] && [scanner isAtEnd];
if(!isNumeric)
return false;
}
return true;
I need equivalent code in Swift 4. I have tried different things but couldn't work it out. The requirement is to check whether the elements of array are number or not.

To check if an object is a number (Int in your case), you could do two things:
Type check via is or as?
This only checks the type and not the content
let isNumberType = "1" is Int
print(isNumberType) //false because "1" is of type String
Creating an Int via it's initializer
This returns an Int? because it can fail so further check != nil
let something = "1"
let isNumber = Int(something) != nil
print(isNumber) //true because "1" can be made into an Int
NOTE: As per your example, you're checking only even elements, hence we will use stride(from:to:by:)
Solution #1:
Assuming you have an array of Strings, we can use the Int initializer to check if the string element can be a number, like so:
func check(expression: [String]) -> Bool {
for idx in stride(from: 0, to: expression.count, by: 2) {
let isNumeric = Int(expression[idx]) != nil
if isNumeric == false {
return false
}
}
return true
}
check(expression: ["1", "A", "2", "B", "3", "C"]) //true
check(expression: ["1", "A", "2", "B", "E", "C"]) //false
Solution #2:
Assuming your array is of type [Any] and you want to type check the alternate elements to be Int then use is, like so:
func check(expression: [Any]) -> Bool {
for idx in stride(from: 0, to: expression.count, by: 2) {
let isNumeric = expression[idx] is Int
if isNumeric == false {
return false
}
}
return true
}
check(expression: [1, "A", 2, "B", 3, "C"]) //true
check(expression: [1, "A", 2, "B", "3", "C"]) //false
The thing with [Any] is that it's elements can't be fed directly to the Int's initializer without bringing it into an acceptable type.
So in this example, for simplicity sake, we are just checking if the object is exactly of type Int or not.
Therefore, I doubt this one suits your requirement.

Try this:
var str = "1234456";
let scanner = Scanner(string: str);
let isNumeric = scanner.scanInt(nil) && scanner.isAtEnd
if !isNumeric {
print("not numeric")
} else {
print("is numeric")
}
Overall if you just want to check the given string is an parsable Integer, I recommend you try :
var expressions = ["1234456","abcd"];
for str in expressions {
if let isNumeric = Int(str) {
print("is numeric")
} else {
print("not numeric")
}
}

Related

Kotlin - How to check if a char is present in a matrix?

Only for context: I am trying to implement Playfair Cipher. It would be really helpful if you take a look at Playfair Cipher to understand my problem.
This program is just for some background:
fun main(){
println("Enter the message:")
var message:String = readLine()!!.toUpperCase()
println("Enter the key:")
var key:String = readLine()!!.toUpperCase()
var cipTable = Array(5){ Array(5){'X'}}
var j=0; //to iterate througm my key
for(innerArray in cipTable){
for(i in innerArray.indices){
if(key[j++] !in cipTable)
innerArray[i]+=key[j]
if(j==key.length) break
}
}
}
My main issue is with this part:
for(innerArray in cipTable){
for(i in innerArray.indices){
if(key[j++] !in cipTable)
I wanted to check if the key that I am going to insert in the matrix is already present in it or not. I also cannot use innerArray instead of cipTable as it would only check for char in the same row. Is there any way I can check if a char is present or not in the entire matrix?
For eg.:
fun main(){
var result = arrayOf(
intArrayOf(3, 2, 4),
intArrayOf(6, 7, 9),
intArrayOf(12, 11, 23)
)
//To check if 2 is present in the entire matrix/table
if(result.any { 2 !in it}) println("not present") else print("present")
}
Can you tell me what is wrong in this code because the output is not expected. Also is there any way I can use forEach for the same.
If I understand correctly, you want this for loop to result in a true or false based on whether any inner array has the same sequence and number of chars as the key String.
First of all, the inner array should be a CharArray instead of an Array<Char>, to avoid boxing.
val cipTable = Array(5) { CharArray(5) { 'X' } }
Then you can use all and contentEquals to check if any of the inner CharArrays are a match for the key.
val charArrayKey = key.toCharArray()
val isKeyInTable = cipTable.any { it.contentEquals(charArrayKey) }
If you want to skip the step of converting the key to a CharArray, you can manually check it like this:
val isKeyInTable =
cipTable.any { it.size == key.length && it.withIndex().all { (i, c) -> c == key[i] } }
I guess one way is to use extensions.
fun Array<IntArray>.has(x:Int):Boolean{
for(innerArray in this){
if(x in innerArray)
return true
}
return false
}
fun main(){
var result = arrayOf(
intArrayOf(3, 2, 4),
intArrayOf(6, 7, 9),
intArrayOf(12, 11, 23)
)
//To check if 43 or 4 is present in the entire matrix/table
if(result.has(43)) println("present") else println("not present")
if(result.has(4)) println("present") else println("not present")
}

Trouble converting NSData Objective-C code to Swift

I've been having issues converting an Objective-C snippet to Swift that uses NSData and CoreBluetooth. I have looked at this question and a couple others dealing with NSData in Swift but haven't had any success.
Objective-C Snippet:
- (CGFloat) minTemperature
{
CGFloat result = NAN;
int16_t value = 0;
// characteristic is a CBCharacteristic
if (characteristic) {
[[characteristic value] getBytes:&value length:sizeof (value)];
result = (CGFloat)value / 10.0f;
}
return result;
}
What I have so far in Swift (not working):
func minTemperature() -> CGFloat {
let bytes = [UInt8](characteristic?.value)
let pointer = UnsafePointer<UInt8>(bytes)
let fPointer = pointer.withMemoryRebound(to: Int16.self, capacity: 2) { return $0 }
value = Int16(fPointer.pointee)
result = CGFloat(value / 10) // not correct value
return result
}
Does the logic look wrong here? Thanks!
One error is in
let fPointer = pointer.withMemoryRebound(to: Int16.self, capacity: 2) { return $0 }
because the rebound pointer $0 is only valid inside the closure and must
not be passed to the outside. Also the capacity should be 1 for a
single Int16 value. Another problem is the integer division in
result = CGFloat(value / 10)
which truncates the result (as already observed by the4kman).
Creating an [UInt8] array from the data is not necessary, the
withUnsafeBytes() method of Data can be used instead.
Finally you could return nil (instead of "not a number") if no
characteristic value is given:
func minTemperature() -> CGFloat? {
guard let value = characteristic?.value else {
return nil
}
let i16val = value.withUnsafeBytes { (ptr: UnsafePointer<Int16>) in
ptr.pointee
}
return CGFloat(i16val) / 10.0
}
You should make the return value optional and check if characteristic is nil in the beginning with a guard. You should also explicitly convert the value to CGFloat, then divide it by 10.
func minTemperature() -> CGFloat? {
guard characteristic != nil else {
return nil
  }
let bytes = [UInt8](characteristic!.value)
let pointer = UnsafePointer<UInt8>(bytes)
let fPointer = pointer.withMemoryRebound(to: Int16.self, capacity: 2) { return $0 }
let value = Int16(fPointer.pointee)
result = CGFloat(value) / 10
return result
}

Objective-C code (array.indexOfObjectPassingTest) to Swift

How can I use the Objective-C code below in Swift, I tried but something is wrong.
Objective-C:
NSUInteger index = [theArray indexOfObjectPassingTest:
^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop)
{
return [[dict objectForKey:#"name"] isEqual:theValue];
}
];
Swift (Doesn't work):
let index = theArray.indexOfObjectPassingTest { (var dict: NSDictionary, var ind: Int, var bool: Bool) -> Bool in
return dict.objectForKey("name")?.isEqual("theValue")
}
I played with it and got this to work:
let theArray: NSArray = [["name": "theName"], ["name": "theStreet"], ["name": "theValue"]]
let index = theArray.indexOfObjectPassingTest { (dict, ind, bool) in return dict["name"] as? String == "theValue" }
if index == NSNotFound {
print("not found")
} else {
print(index) // prints "2"
}
This can be further reduced. As #newacct mentioned in the comment, the return can be dropped since the closure is only a single line. Also, _ can be used in place of the parameters that aren't being used:
let index = theArray.indexOfObjectPassingTest { (dict, _, _) in dict["name"] as? String == "theValue" }
You can get rid of the parameter list in the closure entirely and use the default $0 value. Note in that case, the three parameters are combined as a tuple, so the first value of the tuple dict is referenced as $0.0:
let index = theArray.indexOfObjectPassingTest { $0.0["name"] as? String == "theValue" }
Swift 3:
Consider this method:
public func index(where predicate: (Element) throws -> Bool) rethrows -> Int?
The following gives you an example how to use it:
let dict1 = ["name": "Foo"]
let dict2 = ["name": "Doh"]
let array = [dict1, dict2]
let index = array.index { (dictionary) -> Bool in
return dictionary["name"] == "Doh"
}
This returns the value 1.
Hope that helps
Guess you need this:
var index: UInt = theArray.indexOfObjectPassingTest({(dict: [NSObject: AnyObject], idx: UInt, stop: Bool) -> BOOL in return dict.objectForKey("name").isEqual(theValue)
})
I ended up using this for a Swift5 project:
let index = self.info.indexOfObject(passingTest: { (obj:Any, ind:Int, stop:UnsafeMutablePointer<ObjCBool>) -> Bool in
if let details = obj as? NSDictionary, let id = details["id"] as? Int
{
if (orderId == id)
{
stop.pointee = true
return true
}
}
return false;
})
Where orderId is id value of the object I wanted to find.

How to stop enumerateObjectsUsingBlock Swift

How do I stop a block enumeration?
myArray.enumerateObjectsUsingBlock( { object, index, stop in
//how do I stop the enumeration in here??
})
I know in obj-c you do this:
[myArray enumerateObjectsUsingBlock:^(id *myObject, NSUInteger idx, BOOL *stop) {
*stop = YES;
}];
In Swift 1:
stop.withUnsafePointer { p in p.memory = true }
In Swift 2:
stop.memory = true
In Swift 3 - 4:
stop.pointee = true
This has unfortunately changed every major version of Swift. Here's a breakdown:
Swift 1
stop.withUnsafePointer { p in p.memory = true }
Swift 2
stop.memory = true
Swift 3
stop.pointee = true
since XCode6 Beta4, the following way can be used instead:
let array: NSArray = // the array with some elements...
array.enumerateObjectsUsingBlock( { (object: AnyObject!, idx: Int, stop: UnsafePointer<ObjCBool>) -> Void in
// do something with the current element...
var shouldStop: ObjCBool = // true or false ...
stop.initialize(shouldStop)
})
The accepted answer is correct but will work for NSArrays only. Not for the Swift datatype Array. If you like you can recreate it with an extension.
extension Array{
func enumerateObjectsUsingBlock(enumerator:(obj:Any, idx:Int, inout stop:Bool)->Void){
for (i,v) in enumerate(self){
var stop:Bool = false
enumerator(obj: v, idx: i, stop: &stop)
if stop{
break
}
}
}
}
call it like
[1,2,3,4,5].enumerateObjectsUsingBlock({
obj, idx, stop in
let x = (obj as Int) * (obj as Int)
println("\(x)")
if obj as Int == 3{
stop = true
}
})
or for function with a block as the last parameter you can do
[1,2,3,4,5].enumerateObjectsUsingBlock(){
obj, idx, stop in
let x = (obj as Int) * (obj as Int)
println("\(x)")
if obj as Int == 3{
stop = true
}
}
Just stop = true
Since stop is declared as inout, swift will take care of mapping the indirection for you.

Can someone make me understand how sortedArrayUsingFunction works?

my array has the following:
{
"4eb57e72c7e24c014f000000" : {
"_id" : {
"$id" : "4eb57e72c7e24c014f000000"
},
"author" : "tim",
"comments" : [],
"created": {
"sec" : 1320517234,
"used" : 856000
},
"picture" : "http://someurl.com",
"text" : "this is a test",
"title" : "test",
"type" : ["test"]
}
I want to sort by created (sec value)
this is what I have....I just do not know how sortedArrayUsingFunction works. I mean what am I comparing in the compare function??
jokesArray = [unSortedContentArray sortedArrayUsingFunction:Sort_Created_Comparer context:self];
NSInteger Sort_Created_Comparer(id num1, id num2, void *context)
{
int v1 = [num1 getSecFromJSONValue];
int v2 = [num2 getSecFromJSONValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
num1 and num2 are 2 elements of your array and context is an object that you can pass in to your function to help you with the sort.
Your function will be called many times on the array and the result of the sort will be returned to you in a new array.
Is that what you are wondering?
The comparison function is called to compare two values at a time from your NSArray. This is how the sorting is done.
The comparison function is your way of telling the sort algorithm how you want your objects ordered. Without it, it has no way of knowing what the final order should be.
In your example code the argument names num1 and num2 are very misleading. They would be more accurately named object1 and object2. If object1 should come before object2 then return NSOrderedAscending. If it should come after then NSOrderedDescending otherwise return NSOrderedSame.
To illustrate, here is an example that sorts hypothetical Person objects by age (lowest to highest).
NSInteger youngest_first(id object1, id object2, void *context) {
if (object1.age < object2.age) {
return NSOrderedAscending;
}
else if (object1.age > object2.age) {
return NSOrderedDescending;
}
else {
return NSOrderedSame;
}
}
Notice that I didn't even use the context parameter as my objects themselves had sufficient information to determine the order.
If I instead want them to be sorted by descending height then I could pass the following:
NSInteger tallest_first(id object1, id object2, void *context) {
if (object1.height > object2.height) {
return NSOrderedAscending;
}
else if (object1.height < object2.height) {
return NSOrderedDescending;
}
else {
return NSOrderedSame;
}
}
One thing that is very important is that your function should return a consistent result if the arguments are passed in the other order. For example if tallest_first(adam, joe, NULL) returns NSOrderedDescending then tallest_first(joe, adam, NULL) should return NSOrderedAscending. If not your comparison function contradicts itself.