Confused Confused - 4 days ago 5
Swift Question

Filter, Closure, Functional syntax version of for loop with multiple conditions

I'm trying to learn some ideas of functional programming, as they exist in Swift.

In a recent question, it was shown how much better this can be, by Rickster (the guru).

from this:

var voiceToUse: AVSpeechSynthesisVoice?
let voices = AVSpeechSynthesisVoice.speechVoices()
for voice in voices {
if voice.name == "Arthur"
{
voiceToUse = voice
}
}


to this:

let voiceToUse = AVSpeechSynthesisVoice.speechVoices().filter({ $0.name == "Arthur" }).first


Now I'm wondering how this technique can be applied to a problem where there's multiple criteria. Can this functional style be done to this:

var voiceToUse: AVSpeechSynthesisVoice?
let voices = AVSpeechSynthesisVoice.speechVoices()
for voice in voices {
if voice.name == "Samantha (Enhanced)" && voice.quality == .enhanced
{
voiceToUse = voice
}
}

Answer

If you want the first element of the array that satisfies the criteria use this.

if let voiceToUse = AVSpeechSynthesisVoice.speechVoices().first(where: {
        $0.name == "Samantha (Enhanced)" && $0.quality == .enhanced
    }){

      //use the voiceTouse Variable

    }

If you want the last of the element of the array that satisfies the criteria use this.

if let voiceToUse = AVSpeechSynthesisVoice.speechVoices().reversed().first(where: {
       $0.name == "Samantha (Enhanced)" && $0.quality == .enhanced
    }){

      //use the voiceTouse Variable

    }

yes sure, we can use guard let ...

A guard statement is used to transfer program control out of a scope if one or more conditions aren’t met. in this example, if the condition is not met, ie there is no element in AVSpeechSynthesisVoice.speechVoices() that meet the criteria, guard let will transfer the program control out of the check function ,else if there is the some element in AVSpeechSynthesisVoice.speechVoices() that meet the criteria, program control goes to the next line after the guard let statement

func check(){
guard let voiceToUse =  AVSpeechSynthesisVoice.speechVoices().first(where: {
   $0.name == "Samantha (Enhanced)" && $0.quality == .enhanced
})else{
    return
}
 //use the voiceToUseVariable

}

check()
Comments