Using zip or enumerate within IF?

Hello,
Is there a way to use zip() or enumerate() within the IF statement?
I’m looking for a safter way to run the code below. I’ve created structs to dispatch an appropriate model based off a “category” in a dataframe. Currently it’s only dispatching the custom models correctly because custom_cats and custom_cats_structs are aligned (that is when looping through category: Custom 1, Struct: custom_a is the appropriate choice).

It seems like doing something like zip(custom_cats, custom_cats_structs) would be safer / more preferred way, but I can’t seem to figure out what the right syntax is.

Here’s what I have (which works, but again seems suboptimal):

struct general end
struct custom_a end
struct custom_b end

df = DataFrame(category=["Normal 1", "Normal 2", "Normal 3", "Custom 1", "Custom 2"], X=[5, 4, 8, 9,10], Y =[1000,5000,3000,1200,5000])

cats = ["Normal 1", "Normal 2", "Normal 3", "Custom 1", "Custom 2"]
normal_cats = ["Normal 1", "Normal 2", "Normal 3"]
custom_cats = ["Custom 1", "Custom 2"]
custom_cats_structs = [custom_a(),custom_b()]

function mymodel(x::general)
    println("Genearl Model Hello")
end

function mymodel(x::custom_a)
    println("This is my first custom model")
end

function mymodel(x::custom_b)
    println("This is my second custom model")
end

function run_models(cats,norm,cust,cust_structs)
    for c in cats
        println("working on $c")
        if c in norm
            mymodel(general())
        elseif c in cust
            n = 1
            mymodel(cust_structs[n])
            n+1
        end
    end
end

run_models(cats,normal_cats,custom_cats,custom_cats_structs)

Hope this makes sense. Thanks for your help.

julia> a = [1, 2, 3, 4]; b = [100, 200, 300, 400];

julia> for (ai, bi) in zip(a, b)
           println("ai: ", ai)
           println("bi: ", bi)
       end
ai: 1
bi: 100
ai: 2
bi: 200
ai: 3
bi: 300
ai: 4
bi: 400

Can we ask what the higher level goal is? Like, what end result do you want to get e.g. print something for each item in the data frame? While attempting a solution is good, it can lead to so-called “XY problems”. I also don’t quite understand what the current goal is either.

You essentially have an associative map. The datastructure for this is Dict. Here’s how I would do it:

struct General end
struct CustomA end
struct CustomB end

categories = ["Normal 1", "Normal 2", "Normal 3", "Custom 1", "Custom 2"]
custom_category_selectors = Dict("Custom 1" => CustomA(), "Custom 2" => CustomB())

function mymodel(x::General)
    println("General Model Hello")
end

function mymodel(x::CustomA)
    println("This is my first custom model")
end

function mymodel(x::CustomB)
    println("This is my second custom model")
end

function run_models(categories, custom_selectors)
    for c in categories
        println("working on $c")
        selector = get(custom_selectors, c, General())  # Defaults to General() when c is not a key in custom_selectors
        mymodel(selector)
    end
end

run_models(categories, custom_category_selectors)
# Output
working on Normal 1
General Model Hello
working on Normal 2
General Model Hello
working on Normal 3
General Model Hello
working on Custom 1
This is my first custom model
working on Custom 2
This is my second custom model
1 Like

I’m trying to extend this to parent categories and could use some help.
From the previous solution, imagine that each category exists in a parent category. Simply, I could extend mymodel to include a parent category argument, but custom categories for each parent cat will differ slightly and I’m trying not to repeat myself for functions that aren’t any different. (But perhaps this is the best way?)

Doing something like the following, but I can’t figure out how to select the appropriate parent category and default

Here’s what I have thus far:

struct default_pc end
struct custom_pc1 end
struct custom_pc2 end
struct general_model end
struct custom_model1 end
struct custom_model2 end

categories = ["Normal 1", "Normal 2", "Normal 3", "Custom 1", "Custom 2"]
supercategories = ["custom_pc1","custom_pc2"]
supercats_mapping = Dict(
    custom_pc1() => ["Custom 1" => custom_model1(), "Custom 2" => custom_model2()],
    custom_pc2() => ["Custom 1" => custom_model1()]
)


function mymodel(pc::default_pc,m::general_model) println("This is the most generic model and will be used for any super category if a custom model isn't specified") end
function mymodel(pc::default_pc,m::custom_model1) println("this is the default custom model 1 and is used if the custom1 model isn't specified for a pc") end
function mymodel(pc::default_pc,m::custom_model2) println("this is the default custom model 2 and is used if the custom1 model isn't specified for a pc") end
function mymodel(pc::custom_pc1,m::custom_model1) println("this is the highly specific custom model 1 only used for pc1") end
function mymodel(pc::custom_pc1,m::custom_model2) println("this is the highly specific custom model 2 only used for pc1") end
function mymodel(pc::custom_pc2,m::custom_model1) println("this is the highly specific custom model 1 used only for pc2") end

function run_models(supercats,cats,mapping)
    for s in supercats
        println("working on $s")
        for c in cats
            println("working on $c")
            pc_selector = get(mapping,s,default_pc())
            println("pc selected: $pc_selector")
            m_selector = get(mapping,c,general_model())
            println("model selected: $m_selector")
            mymodel(pc_selector,m_selector)
        end
    end
end

run_models(supercategories,categories,supercats_mapping)

However, I can’t figure out the right selection method here.
Ideally for custom_pc1, it should run:

mymodel(pc::default_pc,m::general_model)

for Normal 1, 2, &3, then it should run:

mymodel(pc::custom_pc1,m::custom_model1) println("this is the highly specific custom model 1 only used for pc1") end
mymodel(pc::custom_pc1,m::custom_model2)

for custom 1 and custom 2.

For custom_pc2, it should run:

mymodel(pc::default_pc,m::general_model)

for Normal 1, 2, 3

mymodel(pc::custom_pc2,m::custom_model1)

for Custom 1
and default back to:

mymodel(pc::default_pc,m::custom_model2)

for Custom 2 (since there is no custom 2 model specified for pc2)

So , I’m a bit lost on an elegant solution here. Perhaps I’ve been working on this problem too long.