Easire way of mass looping through tables in tables?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve?

Simple way of looping through tables in tables.

  1. What is the issue?

I dont know any effective way.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

--Is there any other way of looping through a table to get other tables other than this?

local Table = {
	Table2 = {
		Table3 = {
			"Hello World!"
		}
	}
}

--This
for i, v in pairs(Table) do
	if typeof(v) == typeof({}) then
		for i2, v2 in pairs(v) do
			if typeof(v) == typeof({}) then
				for i3, v3 in pairs(v2) do
					print(i3, v3)
				end
			end
		end
	end
end

-- And this?

print(Table.Table2.Table3[1])

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

Recursion is the easiest way to do this. Recursion is a pretty cool thing when done right. Recursion is when you call a function inside itself. Anything done with recursion can be done with looping btw.

local JsonTab = {
	Table = {
		Table2 = {
			Table3 = {
				"Hello World!";
				'lol'
			}
		}
	}
}

local function Loop(Table, Callback)
	for k, v in pairs(Table) do
		Callback(k,v)
		if type(v) == "table" then
			Loop(v, Callback)
		end
	end
end

Loop(JsonTab, function(k,v)
	print(k, "   ", v)
end)
2 Likes

Thank you. But do you know how I can make print like this?

local Table = {
	Table2 = {
		Table3 = {
			"Hello World!",
		}
	}
}

Instead of like this

  Table     table: 0xa9410f8e09b872f3
  Table2     table: 0xa0fb6ece423b9233
  Table3     table: 0xe8b56dee9db74973
  1     Hello World!

It would help a lot

1 Like

Your require does not work. And I meant like

local Table = {
	"Hello World!"
}

Not

{"Hello World!"}

Would need to hardcode the variable name into the string then.

what do you mean hardcode
ghfgc

The variable name would have to be built into the code. Since on Roblox there isn’t a way to get local variable names

I showed you that resource to get started, not to blindly follow it. First of all there are some settings in repr you can copy. Such as these. local table isn’t supported in repr but you do that yourself, here is an example below.


https://gyazo.com/e0707ca94b734536537ef9e2529a1deb

First of all play around with these settings. Enable pretty and semicolons.

local Repr = require(workspace.repr)

local Table = {
	"Hello World!"
}

local String =  "local table = " ..  Repr(Table)

print(String)


https://gyazo.com/8328773e9ae9c19cfb554d545270adec

You have to hardcore the variable name as Incapaz said, unless that’s if your storing these tables inside an other hashtable.

1 Like

Why does this happen?

local Table = {
	Table2 = {
		"House!"
	},
	"Haps"
}
  local Table = {
  	Table2 = {
  		"House!"
  	},
  	[1] = "Haps"
  }

I dont want the [1]

Because you have a mixed table.

How do I stop the [1] from happening?

--- repr - Version 1.2
-- Ozzypig - ozzypig.com - http://twitter.com/Ozzypig
-- Check out this thread for more info:
-- https://devforum.roblox.com/t/repr-function-for-printing-tables/276575
--[[
 
local repr = require(3148021300)

local myTable = {
	hello = "world",
	score = 5,
	isCool = true
}
print(repr(myTable)) --> {hello = "world", isCool = true, score = 5}
 
]]
 
local defaultSettings = {
	pretty = true;
	robloxFullName = false;
	robloxProperFullName = true;
	robloxClassName = true;
	tabs = true;
	semicolons = false;
	spaces = 3;
	sortKeys = true;
}
 
-- lua keywords
local keywords = {["and"]=true, ["break"]=true, ["do"]=true, ["else"]=true,
["elseif"]=true, ["end"]=true, ["false"]=true, ["for"]=true, ["function"]=true,
["if"]=true, ["in"]=true, ["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true,
["repeat"]=true, ["return"]=true, ["then"]=true, ["true"]=true, ["until"]=true, ["while"]=true}
 
local function isLuaIdentifier(str)
	if type(str) ~= "string" then return false end
	-- must be nonempty
	if str:len() == 0 then return false end
	-- can only contain a-z, A-Z, 0-9 and underscore
	if str:find("[^%d%a_]") then return false end
	-- cannot begin with digit
	if tonumber(str:sub(1, 1)) then return false end
	-- cannot be keyword
	if keywords[str] then return false end
	return true
end
 
-- works like Instance:GetFullName(), but invalid Lua identifiers are fixed (e.g. workspace["The Dude"].Humanoid)
local function properFullName(object, usePeriod)
	if object == nil or object == game then return "" end
	
	local s = object.Name
	local usePeriod = true
	if not isLuaIdentifier(s) then
		s = ("[%q]"):format(s)
		usePeriod = false
	end
	
	if not object.Parent or object.Parent == game then
		return s
	else
		return properFullName(object.Parent) .. (usePeriod and "." or "") .. s 
	end
end
 
local depth = 0
local shown
local INDENT
local reprSettings
 
local function repr(value, reprSettings)
	reprSettings = reprSettings or defaultSettings
	INDENT = (" "):rep(reprSettings.spaces or defaultSettings.spaces)
	if reprSettings.tabs then
		INDENT = "\t"
	end
	
	local v = value --args[1]
	local tabs = INDENT:rep(depth)
	
	if depth == 0 then
		shown = {}
	end
	if type(v) == "string" then
		return ("%q"):format(v)
	elseif type(v) == "number" then
		if v == math.huge then return "math.huge" end
		if v == -math.huge then return "-math.huge" end
		return tonumber(v)
	elseif type(v) == "boolean" then
		return tostring(v)
	elseif type(v) == "nil" then
		return "nil"
	elseif type(v) == "table" and type(v.__tostring) == "function" then
		return tostring(v.__tostring(v))
	elseif type(v) == "table" and getmetatable(v) and type(getmetatable(v).__tostring) == "function" then
		return tostring(getmetatable(v).__tostring(v))
	elseif type(v) == "table" then
		if shown[v] then return "{CYCLIC}" end
		shown[v] = true
		local str = "{" .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or "")
		local isArray = true
		for k, v in pairs(v) do
			if type(k) ~= "number" then
				isArray = false
				break
			end
		end
		if isArray then
			for i = 1, #v do
				if i ~= 1 then
					str = str .. (reprSettings.semicolons and ";" or ",") .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or " ")
				end
				depth = depth + 1
				str = str .. repr(v[i], reprSettings)
				depth = depth - 1
			end
		else
			local keyOrder = {}
			local keyValueStrings = {}
			for k, v in pairs(v) do
				depth = depth + 1
				local kStr = isLuaIdentifier(k) and k or ("[" .. repr(k, reprSettings) .. "]")
				local vStr = repr(v, reprSettings)
				--[[str = str .. ("%s = %s"):format(
					isLuaIdentifier(k) and k or ("[" .. repr(k, reprSettings) .. "]"),
					repr(v, reprSettings)
				)]]
				table.insert(keyOrder, kStr)
				keyValueStrings[kStr] = vStr
				depth = depth - 1
			end
			if reprSettings.sortKeys then table.sort(keyOrder) end
			local first = true
			for _, kStr in pairs(keyOrder) do
				if not first then
					str = str .. (reprSettings.semicolons and ";" or ",") .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or " ")
				end
				str = str .. ("%s = %s"):format(kStr, keyValueStrings[kStr])
				first = false
			end
		end
		shown[v] = false
		if reprSettings.pretty then
			str = str .. "\n" .. tabs
		end
		str = str .. "}"
		return str
	elseif typeof then
		-- Check Roblox types
		if typeof(v) == "Instance" then
			return  (reprSettings.robloxFullName
				and (reprSettings.robloxProperFullName and properFullName(v) or v:GetFullName())
			 or v.Name) .. (reprSettings.robloxClassName and ((" (%s)"):format(v.ClassName)) or "")
		elseif typeof(v) == "Axes" then
			local s = {}
			if v.X then table.insert(s, repr(Enum.Axis.X, reprSettings)) end
			if v.Y then table.insert(s, repr(Enum.Axis.Y, reprSettings)) end
			if v.Z then table.insert(s, repr(Enum.Axis.Z, reprSettings)) end
			return ("Axes.new(%s)"):format(table.concat(s, ", "))
		elseif typeof(v) == "BrickColor" then
			return ("BrickColor.new(%q)"):format(v.Name)
		elseif typeof(v) == "CFrame" then
			return ("CFrame.new(%s)"):format(table.concat({v:GetComponents()}, ", "))
		elseif typeof(v) == "Color3" then
			return ("Color3.new(%d, %d, %d)"):format(v.r, v.g, v.b)
		elseif typeof(v) == "ColorSequence" then
			if #v.Keypoints > 2 then
				return ("ColorSequence.new(%s)"):format(repr(v.Keypoints, reprSettings))
			else
				if v.Keypoints[1].Value == v.Keypoints[2].Value then
					return ("ColorSequence.new(%s)"):format(repr(v.Keypoints[1].Value, reprSettings))
				else
					return ("ColorSequence.new(%s, %s)"):format(
						repr(v.Keypoints[1].Value, reprSettings),
						repr(v.Keypoints[2].Value, reprSettings)
					)
				end
			end
		elseif typeof(v) == "ColorSequenceKeypoint" then
			return ("ColorSequenceKeypoint.new(%d, %s)"):format(v.Time, repr(v.Value, reprSettings))
		elseif typeof(v) == "DockWidgetPluginGuiInfo" then
			return ("DockWidgetPluginGuiInfo.new(%s, %s, %s, %s, %s, %s, %s)"):format(
				repr(v.InitialDockState, reprSettings),
				repr(v.InitialEnabled, reprSettings),
				repr(v.InitialEnabledShouldOverrideRestore, reprSettings),
				repr(v.FloatingXSize, reprSettings),
				repr(v.FloatingYSize, reprSettings),
				repr(v.MinWidth, reprSettings),
				repr(v.MinHeight, reprSettings)
			)
		elseif typeof(v) == "Enums" then
			return "Enums"
		elseif typeof(v) == "Enum" then
			return ("Enum.%s"):format(tostring(v))
		elseif typeof(v) == "EnumItem" then
			return ("Enum.%s.%s"):format(tostring(v.EnumType), v.Name)
		elseif typeof(v) == "Faces" then
			local s = {}
			for _, enumItem in pairs(Enum.NormalId:GetEnumItems()) do
				if v[enumItem.Name] then
					table.insert(s, repr(enumItem, reprSettings))
				end
			end
			return ("Faces.new(%s)"):format(table.concat(s, ", "))
		elseif typeof(v) == "NumberRange" then
			if v.Min == v.Max then
				return ("NumberRange.new(%d)"):format(v.Min)
			else
				return ("NumberRange.new(%d, %d)"):format(v.Min, v.Max)
			end
		elseif typeof(v) == "NumberSequence" then
			if #v.Keypoints > 2 then
				return ("NumberSequence.new(%s)"):format(repr(v.Keypoints, reprSettings))
			else
				if v.Keypoints[1].Value == v.Keypoints[2].Value then
					return ("NumberSequence.new(%d)"):format(v.Keypoints[1].Value)
				else
					return ("NumberSequence.new(%d, %d)"):format(v.Keypoints[1].Value, v.Keypoints[2].Value)
				end
			end
		elseif typeof(v) == "NumberSequenceKeypoint" then
			if v.Envelope ~= 0 then
				return ("NumberSequenceKeypoint.new(%d, %d, %d)"):format(v.Time, v.Value, v.Envelope)
			else
				return ("NumberSequenceKeypoint.new(%d, %d)"):format(v.Time, v.Value)
			end
		elseif typeof(v) == "PathWaypoint" then
			return ("PathWaypoint.new(%s, %s)"):format(
				repr(v.Position, reprSettings),
				repr(v.Action, reprSettings)
			)
		elseif typeof(v) == "PhysicalProperties" then
			return ("PhysicalProperties.new(%d, %d, %d, %d, %d)"):format(
				v.Density, v.Friction, v.Elasticity, v.FrictionWeight, v.ElasticityWeight
			)
		elseif typeof(v) == "Random" then
			return "<Random>"
		elseif typeof(v) == "Ray" then
			return ("Ray.new(%s, %s)"):format(
				repr(v.Origin, reprSettings),
				repr(v.Direction, reprSettings)
			)
		elseif typeof(v) == "RBXScriptConnection" then
			return "<RBXScriptConnection>"
		elseif typeof(v) == "RBXScriptSignal" then
			return "<RBXScriptSignal>"
		elseif typeof(v) == "Rect" then
			return ("Rect.new(%d, %d, %d, %d)"):format(
				v.Min.X, v.Min.Y, v.Max.X, v.Max.Y
			)
		elseif typeof(v) == "Region3" then
			local min = v.CFrame.p + v.Size * -.5
			local max = v.CFrame.p + v.Size * .5
			return ("Region3.new(%s, %s)"):format(
				repr(min, reprSettings),
				repr(max, reprSettings)
			)
		elseif typeof(v) == "Region3int16" then
			return ("Region3int16.new(%s, %s)"):format(
				repr(v.Min, reprSettings),
				repr(v.Max, reprSettings)
			)
		elseif typeof(v) == "TweenInfo" then
			return ("TweenInfo.new(%d, %s, %s, %d, %s, %d)"):format(
				v.Time, repr(v.EasingStyle, reprSettings), repr(v.EasingDirection, reprSettings),
				v.RepeatCount, repr(v.Reverses, reprSettings), v.DelayTime
			)
		elseif typeof(v) == "UDim" then
			return ("UDim.new(%d, %d)"):format(
				v.Scale, v.Offset
			)
		elseif typeof(v) == "UDim2" then
			return ("UDim2.new(%d, %d, %d, %d)"):format(
				v.X.Scale, v.X.Offset, v.Y.Scale, v.Y.Offset
			)
		elseif typeof(v) == "Vector2" then
			return ("Vector2.new(%d, %d)"):format(v.X, v.Y)
		elseif typeof(v) == "Vector2int16" then
			return ("Vector2int16.new(%d, %d)"):format(v.X, v.Y)
		elseif typeof(v) == "Vector3" then
			return ("Vector3.new(%d, %d, %d)"):format(v.X, v.Y, v.Z)
		elseif typeof(v) == "Vector3int16" then
			return ("Vector3int16.new(%d, %d, %d)"):format(v.X, v.Y, v.Z)
		elseif typeof(v) == "DateTime" then
			return ("DateTime.fromIsoDate(%q)"):format(v:ToIsoDate())
		else
			return "<Roblox:" .. typeof(v) .. ">"
		end
	else
		return "<" .. type(v) .. ">"
	end
end
 
return repr

Seems a bit silly to me to fork the module just to prevent it from adding that when you can solve the core problem: the use of mixed tables.

1 Like

I dont know how to do it though

Try searching things such as ‘What is a mixed table, and how to prevent it?’

In general, I don’t recommend MixedTables they don’t save to the datastore, and can’t be json encoded.

This is a mixed table you got there, I don’t recommend it ever:

 local Table = {
      	Table2 = {
      		"House!"
      	},
      	[1] = "Haps
      }

In no real-world scenario, you would have to do this. A mixed table has different datatypes of indexes. In your case, your hashtable has numerical indexes and string indexes.

local Table = {
	Table2 = {
		"House!";
		"Haps"
	},
}

Instead 100% of the time you would do this in the real world. Or even better.

local Table = {
	{
		"House!"
	};
	
	"Haps"
}

Your repr thingy returns:

  local Table = {
     Table2 = {
        "House!"
     },
     [1] = "Haps"
  }

I want it to return:

local Table = {
	Table2 = {
		"House!"
	},
	"Haps"
}```

So how would I go about doing that?

This isn’t my “repr” thing Ozzypig made it. If you want to do that rewrite the module, currently Repr doesn’t support this.

Instead of ignoring suggestions of not using mixed tables, why don’t you actually listen to people who told you not to use mixed tables?

I have I have found this:

			for _, kStr in pairs(keyOrder) do
				if not first then
					str = str .. (reprSettings.semicolons and ";" or ",") .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or " ")
				end
				str = str .. ("%s = %s"):format(kStr, keyValueStrings[kStr])
				first = false
			end

If I change it to:

			for _, kStr in pairs(keyOrder) do
				if not first then
					str = str .. (reprSettings.semicolons and ";" or ",") .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or " ")
				end
				str = str .. ("%s%s"):format("", keyValueStrings[kStr])
				first = false
			end

I get

  local Table = {
     {
        "House!"
     },
     "Haps"
  }

But as you can see the Table2 is missing

Your better of asking here for help how to do the thing your asking: