how to include range for eg 'if numbers are between 1 to 5' in swift [duplicate] - swift

This question already has answers here:
Can I use the range operator with if statement in Swift?
(6 answers)
Closed 6 years ago.
I need to code in swift for 'if numbers are between 1 to 5'
I tried this but it's not working.
if myPercent == (1 ... 5) {
let numberGroup = 1
How do I fix this?

Use contains:
if (1...5).contains(myPercent) {
...
}

contains seems to be the basic manner to work with range.
Here are some additions...
Use pattern matching operator:
if 1...5 ~= myPercent {
//...
}
Use if-case:
if case 1...5 = myPercent {
//...
}

You could just use two conditions to check whether it's in bounds:
if myPercent >= 1 && myPercent <= 5 {
...
}

Consider using an extension combined with a switch statement:
extension Int {
func isBetween(range:Range<Int>) -> Bool {
switch self {
case range:
return true
default:
return false
}
}
}
This makes implementation far easier:
5.isBetween(1...5) // true
6.isBetween(1...5) // false
Note that for this to work in Xcode 8 / Swift 3 you must use the half-open range operator:
5.isBetween(1..<6) // true
6.isBetween(1..<6) // false
So in your instance:
if myPercent.isBetween(1..<6) {
let numberGroup = 1
}
Or perhaps:
let numberGroup = myPercent.isBetween(range: 1..<6) ? 1 : 0

Related

Compare three enums in swift [duplicate]

Does anybody know of a shortcut to test whether three numbers are the same? I know this works:
if number1 == number2 && number2 == number3 {
}
But I would like something cleaner, such as;
if number1 == number2 == number3 {
}
It's quite important as I'm comparing a lot of different values.
You could use a set
if Set([number1, number2, number3]).count == 1 {
...
though I'd argue it isn't as transparent as multiple if clauses
You can use the power of tuples and the Transitive Property of Equality.
if (number1, number2) == (number2, number3) {
}
The clause of this IF is true only when number1 is equals to number2 AND number2 is equals to number3. It means that the 3 values must be equals.
You can add them in an array and use sets:
var someSet = NSSet(array: [2,2,2])
if someSet.count == 1 {
print("Same values")
}
Don't know of anything other than a Set, I'd suggest wrapping it in a function to make your intent clear. Something along these lines:
func allItemsEqual<T>(items:[T]) -> Bool {
guard items.count > 1 else { fatalError("Must have at least two objects to check for equality") }
return Set(items).count == 1
}
func allItemsEqual(items:T...) -> Bool {
return equal(items)
}
if allItemsEqual(2,3,2) {
// false
}
if allItemsEqual(2, 2, 2) {
// true
}
Beyond that, maybe you could get fancy with operator overloading?
Try this:
func areEqual<T: NumericType>(numbers: T...) -> Bool {
let num = numbers[0]
for number in numbers {
if number != num {
return false
}
}
return true
}
Where NumericType is defined in this post: What protocol should be adopted by a Type for a generic function to take any number type as an argument in Swift?
This will allow you to use the function for all number types
You just pass any number of numbers like:
//returns true
if areEqual(1, 1, 1) {
print("equal")
}

How to get # of distinct characters in a string? (Swift 4.2 + )

This algorithm or code should work for any # of unique character in a string, by the condition we use to check after.
For instance (If I have a string that I want to know if we have at least 7 unique characters we can do):
let number_of_distinct = Set(some_string.characters).count
if(number_of_distinct >= 7)
{
// yes we have at least 7 unique chars.
}
else
{
// no we don't have at least 7 unique chars.
}
However, this technique seems to be deprecated in Swift 4.2 +, due to the way Strings were updated in Swift 4.0 +.
What would be the new correct approach for this technique mentioned above?
Just remove the .characters
let number_of_distinct = Set(some_string).count
if(number_of_distinct >= 7)
{
print("yes")
// yes we have at least 7 unique chars.
}
else
{
print("no")
// no we don't have at least 7 unique chars.
}
You can also do this without using the Set.
func printUniqueCompleteSubString(from string: String) {
var uniquString = ""
uniquString = string.reduce(uniquString) { (result, char) -> String in
if result.contains(char) {
return result
}
else {
return result + String.init(char)
}
}
print("Unique String is:", uniquString)
}

How do a i+=2 for-loop in Swift? [duplicate]

This question already has answers here:
Swift 3 for loop with increment
(5 answers)
Closed 5 years ago.
for example, a Java for-loop:
for(int i=0; i<5; i+=1){
//
}
convert to Swift
for index in 0..<5 {
}
but what if i+=2?
I'm new to Swift.. Maybe it's a stupid question, but will be appreciate if you answer it, thx! :-)
Check this
for index in stride(from: 0, to: 5, by: 2){
print(index)
}
You can use this way as well.
var first = 0
var last = 10
var add = 2
for i in sequence(first: first, next: { $0 + add })
.prefix(while: { $0 <= last }) {
print(i)
}
Output will be: 0,2,4,6,8,10
In case if your for loop was doing something more complex than adding constant value to index each iteration you may use something like that:
Assuming you have this for loop:
for(index = initial; condition(index); mutation(index)){
//
}
Where
initial — initial value constant of type T
condition — function (T) -> Bool, that checks if loop should end
mutation — function (T) -> T, that changes index value each iteration
Then it will be:
for index in sequence(first: initial, next: { current in
let next = mutation(current)
return condition(next) ? next : nil
}) {
//
}

How to split or iterate over an Int without converting to String in Swift [duplicate]

This question already has answers here:
Break A Number Up To An Array of Individual Digits
(6 answers)
Closed 5 years ago.
I was wondering if there was a way in Swift to split an Int up into it's individual digits without converting it to a String. For example:
let x: Int = 12345
//Some way to loop/iterate over x's digits
//Then map each digit in x to it's String value
//Return "12345"
For a bit of background, I'm attempting to create my own method of converting an Int to a String without using the String description property or using String Interpolation.
I've found various articles on this site but all the ones I've been able to find either start with a String or end up using the String description property to convert the Int to a String.
Thanks.
Just keep dividing by 10 and take the remainder:
extension Int {
func digits() -> [Int] {
var digits: [Int] = []
var num = self
repeat {
digits.append(num % 10)
num /= 10
} while num != 0
return digits.reversed()
}
}
x.digits() // [1,2,3,4,5]
Note that this will return all negative digits if the value is negative. You could add a special case if you want to handle that differently. This return [0] for 0, which is probably what you want.
And because everyone like pure functional programming, you can do it that way too:
func digits() -> [Int] {
let partials = sequence(first: self) {
let p = $0 / 10
guard p != 0 else { return nil }
return p
}
return partials.reversed().map { $0 % 10 }
}
(But I'd probably just use the loop here. I find sequence too tricky to reason about in most cases.)
A recursive way...
extension Int {
func createDigitArray() -> [Int] {
if self < 10 {
return [self]
} else {
return (self / 10).createDigitArray() + [self % 10]
}
}
}
12345.createDigitArray() //->[1, 2, 3, 4, 5]
A very easy approach would be using this function:
func getDigits(of number: Int) -> [Int] {
var digits = [Int]()
var x = number
repeat{
digits.insert(abs(x % 10), at: 0)
x/=10
} while x != 0
return digits
}
And using it like this:
getDigits(of: 97531) // [9,7,5,3,1]
getDigits(of: -97531) // [9,7,5,3,1]
As you can see, for a negative number you will receive the array of its digits, but at their absolute value (e.g.: -9 => 9 and -99982 => 99982)
Hope it helps!

How can I check if a string contains letters in Swift? [duplicate]

This question already has answers here:
What is the best way to determine if a string contains a character from a set in Swift
(11 answers)
Closed 7 years ago.
I'm trying to check whether a specific string contains letters or not.
So far I've come across NSCharacterSet.letterCharacterSet() as a set of letters, but I'm having trouble checking whether a character in that set is in the given string. When I use this code, I get an error stating:
'Character' is not convertible to 'unichar'
For the following code:
for chr in input{
if letterSet.characterIsMember(chr){
return "Woah, chill out!"
}
}
You can use NSCharacterSet in the following way :
let letters = NSCharacterSet.letters
let phrase = "Test case"
let range = phrase.rangeOfCharacter(from: characterSet)
// range will be nil if no letters is found
if let test = range {
println("letters found")
}
else {
println("letters not found")
}
Or you can do this too :
func containsOnlyLetters(input: String) -> Bool {
for chr in input {
if (!(chr >= "a" && chr <= "z") && !(chr >= "A" && chr <= "Z") ) {
return false
}
}
return true
}
In Swift 2:
func containsOnlyLetters(input: String) -> Bool {
for chr in input.characters {
if (!(chr >= "a" && chr <= "z") && !(chr >= "A" && chr <= "Z") ) {
return false
}
}
return true
}
It's up to you, choose a way. I hope this help you.
You should use the Strings built in range functions with NSCharacterSet rather than roll your own solution. This will give you a lot more flexibility too (like case insensitive search if you so desire).
let str = "Hey this is a string"
let characterSet = NSCharacterSet(charactersInString: "aeiou")
if let _ = str.rangeOfCharacterFromSet(characterSet, options: .CaseInsensitiveSearch) {
println("true")
}
else {
println("false")
}
Substitute "aeiou" with whatever letters you're looking for.
A less flexible, but fun swift note all the same, is that you can use any of the functions available for Sequences. So you can do this:
contains("abc", "c")
This of course will only work for individual characters, and is not flexible and not recommended.
The trouble with .characterIsMember is that it takes a unichar (a typealias for UInt16).
If you iterate your input using the utf16 view of the string, it will work:
let set = NSCharacterSet.letterCharacterSet()
for chr in input.utf16 {
if set.characterIsMember(chr) {
println("\(chr) is a letter")
}
}
You can also skip the loop and use the contains algorithm if you only want to check for presence/non-presence:
if contains(input.utf16, { set.characterIsMember($0) }) {
println("contains letters")
}