Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Is there a way to combine "for" loops?

Asked by 9 years ago

I have a script in my game that selects all the parts of 10 models and changes their transparency. Problem is, the script is pretty long when using 10 for loops for every model. And no, I can't combine all the parts into 1 model, because it would ruin other scripts I have for my game. Simply, I want to know if there's a way to turn this type of code:

local model1 = game.Workspace.model1:GetChildren()
for i = 1, #model1 do
    model1[i].Transparency = 1
end

local model2 = game.Workspace.model2:GetChildren()
for i = 1, #model2 do
    model2[i].Transparency = 1
end

local model3 = game.Workspace.model3:GetChildren()
for i = 1, #model3 do
    model3[i].Transparency = 1
end

--etc

into something with maybe 5 lines.

2 answers

Log in to vote
2
Answered by
Redbullusa 1580 Moderation Voter
9 years ago

I'm quite unsure about combining "for" loops except to tell you to nest them together and put the model variables in a table like so:


model1 = game.Workspace.model1:GetChildren() model2 = game.Workspace.model2:GetChildren() model3 = game.Workspace.model3:GetChildren() MODELtable = {model1, model2, model3} for i = 1, #MODELtable do for i2 = 1, #MODELtable[i] do MODELtable[i][i2].Transparency = 1 end end

But you could also combine tables with a function instead.

totalmodel = {}         -- Initialized the total children of all models, which has a length of 0.

model1 = game.Workspace.model1:GetChildren()

model2 = game.Workspace.model2:GetChildren()

model3 = game.Workspace.model3:GetChildren()

function tableinsert(TABLE)     -- TABLE is the argument for efficiency.
    for i = 1, #TABLE do
        table.insert(totalmodel, (#totalmodel + 1), TABLE[i])   -- Adds the elements in the totalmodel table.
    end
end

tableinsert(model1)

tableinsert(model2)

tableinsert(model3)

for i = 1, #totalmodel do
    totalmodel[i].Transparency = 1
end

-- Both code tested and works.

Check back with me if you have any questions.

1
Thanks. I am kind of new to tables, and this is a bit confusing for me. When you have a line saying "tableinsert(model1)," the (model1) turns into the table used in the function, correct? Also, what does the (totalmodel + 1) do? whyOmustOitObeOme 7 — 9y
1
Yes, the items in "model1" will be used to insert in the "totalmodel" table. Redbullusa 1580 — 9y
1
Just tested this and it works. Thanks! whyOmustOitObeOme 7 — 9y
1
The (#totalmodel + 1) operation adds the items in the table so that it wouldn't overwrite with the first index. For example, the length of table "totalmodel" in line 1 is 0, as there are 0 items in there. I must add 1, elsewise the first index of the model table will be 0. Redbullusa 1580 — 9y
View all comments (2 more)
0
You're welcome. :D Redbullusa 1580 — 9y
0
Ok, thanks a lot. whyOmustOitObeOme 7 — 9y
Ad
Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

For your particular code, we can see that we're just repeating the same code, so it might just make more sense to make a function:

function hide(model)
    for _, part in pairs(model:GetChildren()) do
        part.Transparency = 1
    end
end

hide(game.Workspace.model1)
hide(game.Workspace.model2)
hide(game.Workspace.model3)

I use a generic for loop instead to be a bit cleaner -- you avoid having to say model[i], which I think makes it much easier to read / understand.

If you have a bunch of these models to do this to, it's now easy to make that into a loop:

for _, mod in pairs(workspace.Hidden:GetChildren()) do
    hide(mod)
end

Here's a stranger way to do it, that turns out to be the same (just for fun)

m1 = workspace.model1:GetChildren()
m2 = workspace.model2:GetChildren()
m3 = workspace.model3:GetChildren()

for i = 1, #m1 + #m2 + #m3 do
    local which
    if i <= #m1 then
        which = m1
    else
        i = i - #m1
        if i <= #m2 then
            which = m2
        else
            i = i - #m2
            which = m3
        end
    end
    local part = which[i]
    part.Transparency = 1
end

This is for the particular case of 3 models. It basically jams the three lists next to each other, so that once one list ends, the next begins at the next index.

This is a mess to do, so let's not do that. If we make it more general, it actually cleans up:

local ms = {m1, m2, m3}

local total = 0
for _, m in pairs(ms) do
    total = total + #m
end

for i = 1, total do
    local which = 1
    while i > #ms[which] do
        i = i - #ms[which]
        which = which + 1
    end
    ms[which][i].Transparency = 1
end

This still isn't very clean. The reason is clear in the last line; our outer loop uses i but the first thing we care about is which, so we should just flip them:

for which = 1, #ms do
    for i = 1, #ms[which] do
        ms[which][i].Transparency = 1
    end
end

which, which generic for loops, looks much neater:

for _, m in pairs(ms) do
    for _, part in pairs(m) do
        part.Transparency = 1
    end
end

(Which is the straightforward top solution)

Answer this question