Swift operator for substring string substitution

I am trying to set some values ​​from a variable. The variable will have a description of the weather, and I want to ask for specific words to show different images (like sun, rain or so on) The thing is, I have code like this:

    if self.descriptionWeather.description.rangeOfString("Clear") != nil
{
    self.imageWeather.image = self.soleadoImage
}
if self.descriptionWeather.description.rangeOfString("rain") != nil
{
    self.imageWeather.image = self.soleadoImage
}
if self.descriptionWeather.description.rangeOfString("broken clouds") != nil
{
    self.imageWeather.image = self.nubladoImage
}

      

Because when I tried to add an OR condition, xcode gives me some strange errors.

Can a swich proposal be made with this? Or does anyone know how to do this, add an OR condition to the if clause?

+5


source to share


7 replies


Swift language has two types of operators OR

- bitwise |

(single vertical line) and boolean ||

(double vertical line). In this situation, you need a boolean OR

:

if self.descriptionWeather.description.rangeOfString("Clear") != nil || self.descriptionWeather.description.rangeOfString("clear") != nil {
    self.imageWeather.image = self.soleadoImage
}

      



Unlike Objective-C, where you can get away with different things OR

in exchange for slightly different runtime semantics, Swift requires boolean OR

in the expression above.

+4


source


I had a similar issue today and realized that this question hasn't been updated since Swift 1! This is how I solved it in Swift 4:



switch self.descriptionWeather.description {
case let str where str.contains("Clear"):
    print("clear")
case let str where str.contains("rain"):
    print("rain")
case let str where str.contains("broken clouds"):
    print("broken clouds")
default:
    break
}

      

+12


source


You can do this with a switch statement with value binding and clause where

. But first convert the string to lowercase!

var desc = "Going to be clear and bright tomorrow"

switch desc.lowercaseString as NSString {
case let x where x.rangeOfString("clear").length != 0:
    println("clear")
case let x where x.rangeOfString("cloudy").length != 0:
    println("cloudy")
default:
    println("no match")
}

// prints "clear"

      

+9


source


If you do this a lot, you can implement your own operator ~=

that matches the substring:

import Foundation

public struct SubstringMatchSource {
    private let wrapped: String

    public init(wrapping wrapped: String) {
        self.wrapped = wrapped
    }

    public func contains(_ substring: String) -> Bool {
        return self.wrapped.contains(substring)
    }

    public static func ~= (substring: String, source: SubstringMatchSource) -> Bool {
        return source.contains(substring)
    }
}

extension String {
    var substrings: SubstringMatchSource {
        return SubstringMatchSource(wrapping: self)
    }
}

switch "abcdefghi".substrings {
    case "def": // calls '"def" ~= "abcdefghi".substrings'
        print("Found substring: def") 
    case "some other potential substring":
        print("Found \"some other potential substring\"")
    default: print("No substring matches found")
}

      

+2


source


+1


source


Continuing on Alexander's answer by implementing Marting R's suggestion in the comments, we can implement the pattern matching operator in StringProtocol. There is no need to create an additional type:

extension StringProtocol where Index == String.Index {
    public static func ~= (string: Self, subSequence: SubSequence) -> Bool {
        return subSequence.contains(string)
    }
    var subSequence: SubSequence {
        return self[...]
    }
}

      


let sentence = "Going to rain tomorrow"
switch sentence.subSequence {
case "clear":
    print("Found: clear")
case "rain":
    print("Found: rain")  // "Found: rain\n"
case "broken clouds":
    print("Found: broken clouds")
default:
    print("no matches")
}

      

0


source


Instead, I would recommend using a dictionary as a mapping between the desired substring and the corresponding image:

func image(for weatherString: String) -> UIImage? {
    let imageMapping = [
        "Clear": self.soleadoImage,
        "rain": self.soleadoImage,
        "broken clouds": self.nubladoImage]
    return imageMapping.first { weatherString.contains($0.key) }?.value
}

      

The dictionary gives you flexibility by adding new mappings easily.

0


source







All Articles