Find a string within a string?

I have this var:

Code Block
//genes
var extGene = "ee"
var agoGene = "aa"
var creGene = "crcr"
//genotype
var genotype = extGene + agoGene + creGene

The genotype can appear in different variations like "eeaacrcr", "EeAaCrcr" or "EEAACrCr", but there are a lot more combinations. Sometimes the letters in the genes can appear in random order, for example "Ee" or "eE". I am using this switch statement which is getting too complex:

Code Block
switch (extGene, agoGene, creGene) {
                case
                ("EE", "aa", "crcr"),
                ("Ee", "aa", "crcr"),
                    ("eE", "aa", "crcr"):
                basPhenotype = (blackArray.randomElement()!)
                case
                ("ee", "aa", "crcr"),
                ("ee", "Aa", "crcr"),
                    ("ee", "aA", "crcr"),
                ("ee", "AA", "crcr"):
                basPhenotype = (chestnutArray.randomElement()!)
                        
                case
                ("EE", "AA", "crcr"),
                ("Ee", "AA", "crcr"),
                ("eE", "AA", "crcr"),
                ("EE", "Aa", "crcr"),
                ("EE", "aA", "crcr"),
                ("Ee", "Aa", "crcr"),
                    ("eE", "Aa", "crcr"),
                    ("Ee", "aA", "crcr"),
                    ("eE", "aA", "crcr"):
                basPhenotype = (bayArray.randomElement()!)

Instead it would be nice to just search the genotype for single letters, irrespective of what order they are in, maybe something like this

if genotype contains "e" + "E" {
uiImage = image1
}

if genotype contains "ee" {
uiImage = image2
}

Does anyone know of a way to simplify the code?
Answered by OOPer in 646010022
If you define a matching operator as follows:
Code Block
extension Array where Element == String {
static func ~= (pattern: Self, value: String) -> Bool {
return pattern.contains(value)
}
}


Then you can write a switch statement like this:
Code Block
switch (extGene, agoGene, creGene) {
case (["EE","Ee","eE"], "aa", "crcr"):
basPhenotype = (blackArray.randomElement()!)
case ("ee", ["AA","Aa","aA","aa"], "crcr"):
basPhenotype = (chestnutArray.randomElement()!)
case (["EE","Ee","eE"], ["AA","Aa","aA"], "crcr"):
basPhenotype = (bayArray.randomElement()!)
default:
break
}


But there may be some better ways if you use your own types (for example, Swift enum) for genes.
Looks like creGene is only "crcr". Exact ?

So you could ignore it.

There may be other ways to express like
Code Block
if genotype.contains ("crcr") { // Just in case in the future
if genotype.contains ("aa") && !genotype.contains("ee") {
basPhenotype = (blackArray.randomElement()!)
} else if genotype.contains("ee") {
basPhenotype = (chestnutArray.randomElement()!)
} else {
basPhenotype = (bayArray.randomElement()!)
}
}


But that may be less readable than your switch.
Accepted Answer
If you define a matching operator as follows:
Code Block
extension Array where Element == String {
static func ~= (pattern: Self, value: String) -> Bool {
return pattern.contains(value)
}
}


Then you can write a switch statement like this:
Code Block
switch (extGene, agoGene, creGene) {
case (["EE","Ee","eE"], "aa", "crcr"):
basPhenotype = (blackArray.randomElement()!)
case ("ee", ["AA","Aa","aA","aa"], "crcr"):
basPhenotype = (chestnutArray.randomElement()!)
case (["EE","Ee","eE"], ["AA","Aa","aA"], "crcr"):
basPhenotype = (bayArray.randomElement()!)
default:
break
}


But there may be some better ways if you use your own types (for example, Swift enum) for genes.
Find a string within a string?
 
 
Q