For i, v in pairs VS. for i =

So, there is two types of for loops. But, why should I use one over the other? I know that for i, v in pairs loops through a table, but I can do that same thing in a normal for loop.

for i = 1, #tableName do
    local value = tableName[i] -- Gets the value.
end

You could use both for either.

I personally use

for i=1, #tableName do
    local value = tableName[i]
end

For a specific count like looping tables. However if there’s no specific count you can do:

for _, v in ipairs(obj:GetChildren()) do
    local value = v
end

For looping through children. However both would work, yet I don’t believe there’s a huge difference, someone could correct me on that please.

Also it’s considered best practice to add a wait or delay to any loop for any large counts. As it will cause lag and exceed runtime limits and break the script. However for small loops that you need to run very quickly like checking for events on multiple instances you would not need a wait.

Best, TheROBLOXMAPMAKE :smiley:

1 Like

Let’s say for example, we’d like to loop through all the children in the workspace, and if we find a part named “DemoPart” then, we want to destroy it. We would use a for i,v in pairs loop also known as an enhanced for loop. But to put the children into the workspace in a table, we’d use a function called GetChildren().

for i,v in pairs(game.Workspace:GetChildren()) do -- For ALL the children in the workspace, put them in a table
    if v.Name == "DemoPart" then -- Checking to see if there is a part named DemoPart
        v:Destroy()

Now the i,v is a variable name, you can name them whatever you like. For i,v in pairs is used for iterating things whereas for loops are to repeat things for a certain amount of time, like timers!

He didn’t ask about pairs() vs ipairs(), please read the title.


The difference is just simplicity afaik, it’s just shorter.

1 Like

Unless you’re iterating over a dictionary. You need to use next, or by extension, pairs, to iterate over a dictionary.

Also, you can use any iterator function in a generic for loop. Such as string.gmatch.

for word in string.gmatch("Print each word separately", "%w+") do
    print(word)
end

You can also make your own iterator functions, which can be useful.

I see, in that case

using ‘i =’ uses 1 less variable when looping children

local Children = workspace:GetChildren()
for i = 1, #Children do
    print(Children[i].Name)
end

and

local Children = workspace:GetChildren()
for i, v in pairs(Children()) do
  print(v.Name)
end
1 Like

You don’t need to use next, hence why ipairs() and pairs() are commonly taught when reviewing loops. In fact there’s no definite way to do a loop, there are quite a few options, such as i=1, count, increment or _,v in ipairs(array) or i,v in pairs(array) you can do a mix of them, it doesn’t matter. It’s a loop and there’s no actual performance difference on a large scale.

On the contrary, there are two formats to use with a for loop, and the arguments are dependant on the type of loop.
A numeric for loop is the standard one.
for variable = start, end [, increment] do
It’s the simplest type of for loop as it only takes two or three arguments and has one output.

A generic for loop calls an iterator function.
for variable(s) in iterFunc [, argument(s)] do
The iterator function can be pretty much anything, do pretty much anything, and return any number of variables. They’re super cool, actually. Here are some examples of stateless iterator functions I just threw together.

local function ChildIter(inst)
    local t = inst:GetChildren()
    return function(t, i)
        i = i + 1
        if not t[i] then return end
        return i, t[i].Name, t[i]
    end, t, 0
end

for num, name, object in ChildIter(workspace) do
    print(name) -- Prints the name of every object in Workspace.
end
local function f(_,i)
  i = i and i + 1 or 1
  if i > 10 then return end
  return i
end

for n in f do print(n) end -- Prints 1 through 10.

For more information, read over chapter 7 of PIL.

Your loop can’t handle looping through key value (associative) tables:

local tableKV = {test = "hey", test2 = "hey2"}

It’s the same as an ipairs (index value) loop and ipairs loops can’t handle key value tables either whereas pairs can handle both types, index value and key value tables.

Why? What’s the difference between key value and index value tables?

Take these two tables:

local tableKV = {["test1"] = "hey1", ["test2"] = "hey2"}
local tableName = {"hey", "there"}

If you try to print tableName, you will see that it prints the indexes in the same key value format as tableKV when you run the script. However, they are indexes, meaning that they are constructed from 1 and up.

If you construct a key value table in the very same format as an index value table:
local tableIDX = {[1] = "hey1", [2] = "hey2"}

Then you will be able to loop through this with your loop / ipairs loop! But if you mess with the order, say you add 231 as the index, then it won’t work, it will look for the next first index value and it will find 2 which is not 1, so it won’t print the value.

Also, if you add other values in there like strings or variables as keys, then pairs loop is the way to go.

for i, v in pairs() do can be used with dictionary, and also can be used with tables.

  > local t={123123123123123,123,1,23,12,31,23,12,31,23,1,23,123,1,23,123,12,3,123,12,31,23,12,31,23,12,31,23,12,31,23,123} local s=os.clock() for i =1, 1000000 do for i =1,#t do local v=t[i] end end print(os.clock()-s)
  0.25373430000036
  > local t={123123123123123,123,1,23,12,31,23,12,31,23,1,23,123,1,23,123,12,3,123,12,31,23,12,31,23,12,31,23,12,31,23,123} local s=os.clock() for i =1, 1000000 do for _, v in ipairs(t) do end end print(os.clock()-s)
  0.18597190000582
  > local t={123123123123123,123,1,23,12,31,23,12,31,23,1,23,123,1,23,123,12,3,123,12,31,23,12,31,23,12,31,23,12,31,23,123} local s=os.clock() for i =1, 1000000 do for _, v in next, t do end end print(os.clock()-s)
  0.18401409999933
  > local t={123123123123123,123,1,23,12,31,23,12,31,23,1,23,123,1,23,123,12,3,123,12,31,23,12,31,23,12,31,23,12,31,23,123} local s=os.clock() for i =1, 1000000 do for _, v in pairs(t) do end end print(os.clock()-s)
  0.20235510001658

Arrays:
1.next
2.ipairs
3.pairs
4. generic for loop

What about dictionaries??

  > local t={} for i =97, 97+26 do t[string.char(i)]=true end local s=os.clock() for i =1, 1000000 do for _, v in pairs(t) do end end print(os.clock()-s)
  0.19222349999472
  > local t={} for i =97, 97+26 do t[string.char(i)]=true end local s=os.clock() for i =1, 1000000 do for _, v in next, t do end end print(os.clock()-s)
  0.17488389997743

next is the superior way to traverse dictionaries. For me at least.
Pick your poison.

The difference is between each is around 0.0000003 seconds. That’s 30 nanoseconds, orders of magnitude faster than the time it takes for your computer to render a single frame. There is no realistic impact on performance, whichever you should use depends on the use case.

If the order you iterate over the table doesnt matter, use pairs or next. If you need to iterate over the table in order (such as from 1 to 10), use ipairs.

Using for i = 1, #table do instead of for i, v in pairs(table) won’t affect your game’s performance at all, and in my opinion just makes your code harder to read, especially when someone does table[i].Property = Value. Deciding between using pairs or next is just a matter of preference.

If you need to change pairs for next because you’re doing something millions of times a second and genuinely need the performance boost, you should seriously rethink if you really need to do said thing millions of times a second..

3 Likes

The performance gained from using next does not stack based on the size of the table, it is a one-time bonus. If you’re stressed about performance to that degree, you should be using a numeric loop instead. But that kind of performance boost is not something you should ever care about in game design. If this were something like cryptology, database handling, or mathematics, it might matter a little more.