Confusion about next() function?

It probably sorts them by alphabetical order.

I thought that too but when I tried making it alphabetical it still didn’t work

I thought dictionaries weren’t ordered in a specific order unless you used table.sort, correct me if I’m wrong.

1 Like

Dictionaries aren’t ordered, even if you use table.sort on them. Only normal tables can be sorted.

2 Likes

Are they not? That’s the first time I’m hearing of this. I’ll try to sort it first and then see what it prints out!

Evidently not from cody’s reply. What’s wrong with indexing your dictionary ftr?

1 Like

You can’t index dictionaries, you can only do that with arrays.

local myArray = {"apple", 2, true}
print(myArray[1]) --Prints 'apple'

local myDictionary = {
   ["Apple"] = "apple"
   ["2"] = 2
   ["true"] = true
}

print(myDictionary[1]) -- Prints nil

Index with it myDictionary["Apple"].

You could sort it like this but I don’t think it’s practical unless absolutely necessary. I think this is the thing I confused myself with on table.sort

local myArray = {"apple", 2, true}
print(myArray[1]) --Prints 'apple'

local myDictionary = {
   ["Apple"] = "apple"
   ["2"] = 2
   ["true"] = true
}

print(myDictionary[1]) -- Prints nil
print(myDictionary["Apple"]) -- Prints 'apple' (same as myDictionary.apple)`

Something that helped me learn this was how Roblox’s objects are structured. They’re basically all arrays like ths:

local part = { --> locked with something like table.freeze internally (except for non-readonly properties)
Name = "Object",
ClassName = "Part"
...
}
1 Like

You can index dictionaries using the specific key. For example myDictionary["Apple"] or myDictionary.Apple

The reason I don’t want to index the dictionary is because I have a quest system in my game and to make it easy to make new quests I need to use dictionaries but I don’t want to have a million if statements checking for what quest they’re(the player) on.

Honestly you should create an entire system for this, if you want to avoid messy code habits.

That’s what I’m trying to do but to begin making the system I need to know how to do it(which so far I do not know how).

Can you go in detail for what you want to achieve? I’d like to help my best, but I need more information. We might need to move this to PMs if it becomes spammy back and forth replies, but I’m not sure about the rules on the forum regarding this.

1 Like

First figure out the intended behavior of your system, then cut it down into patterns of code, and then into a lot smaller problems easier to solve.

You can simulate a dictionary order if you make a table with all indexes like this:

local myDict = {
    ['new'] = {};
    ['quick'] = {};
    ['cya'] = {};
}

----- example 1 -----
local indexes = {}

for i,v in pairs(myDict) do
    indexes[#indexes + 1] = i
end
table.sort(indexes) -- should put it in an order similar to alphabetical (can't remember the name), iirc it has a bit of a difference but it's negligible when working with alphanumeric characters
-- now, if we use next on indexes, we can do something like this:
print(next(indexes)) --> cya
local _, value = next(indexes)
local newValue = dict[value] -- should return the entry whose key is "cya"
----- end of example 1 -----

-- if you want, you can also manually define them:
local indexes = {'new', 'quick', 'cya'} -- new should be the first entry, or index 1
local _, value = next(indexes) --> new
print(value) --> new again
local new = myDict[value] -- should return a value whose index is "new"
1 Like

So I have a module in my game called “QuestsInfo” and here’s out it’s currently formatted:

local questInfo = {}

questInfo.CataclysmicDev = {
	["New"] = {
		["Name"] = "New",
		["Type"] = "Strength",
		["Amount"] = 0,
		["Reward"] = 0,
		["GivesPower"] = false
	},
	
	["Quick Training Session"] = {
		["Name"] = "Quick Training Session",
		["Type"] = "Strength",
		["Amount"] = 100,
		["Reward"] = 200,
		["GivesPower"] = false
	},
	
	["Cya!"] = {
		["Name"] = "Cya!",
		["Type"] = "Endurance",
		["Amount"] = 100,
		["Reward"] = 200,
		["GivesPower"] = false
	}
}

return questInfo

And so far I can figure out which quest they’re on but do to it being a dictionary I can’t just go to the next index afterwards. Currently I have a function to get the next quest and then change the player’s current quest to the next one:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local events = ReplicatedStorage:WaitForChild("Events")
local questEvents = events:WaitForChild("QuestEvents")

questEvents.GetQuest.OnServerEvent:Connect(function(player)
	
	local questInfoModule = require(ServerStorage.Modules:WaitForChild("QuestInfo"))
	local questOn = player.QuestInfo.QuestName.Value
	local quest = questInfoModule.CataclysmicDev[questOn]
	local nextQuest = ""
	local num = 1
	
	for i, v in pairs(questInfoModule.CataclysmicDev) do
		
		if v == quest then
			
			if num >= #questInfoModule.CataclysmicDev then
				
				nextQuest = next(questInfoModule.CataclysmicDev)
			else
				nextQuest = next(questInfoModule.CataclysmicDev, i)
			end
			
			break
		end
		
		num += 1
	end
	
	print(nextQuest)
end)

You could order them like this? The only informality (imo) being that you need to index twice.

local quests = {
{{ -- surrounded in a table so it can be indexed with a key
quest = "hi"
}},
{{ 
quest = "hi2"
}}
}
print(quests[1]) --> {[1] = {quest = "hi"}}
print(quests[1][1]) --> {quest = "hi"}

So that’s a possible solution, as is; hacky dictionary sorting and this.

1 Like

Another solution is to store the quest “data” inside each position(for example name, value):

local quests = {
	[1] = {"new", 2},
	[2] = {"quick", "test"}
}

local quest = quests[math.random(1, #quests)]
local name = quest[1]
local value = quest[2]
print(name, value)
--this also can scale if you add more parameters for example quest[3] = the reward
3 Likes

I never thought about doing it like that! This should be easy enough to change. I’ll try it right now and hopefully this won’t be too hard to get working(currently I’m figuring out what quest to find in the dictionary with a StringValue inside of a folder in the player so I’ll just have to figure out how to find it without the StringValue which should be easy enough with a for loop). Thanks :slightly_smiling_face:
Edit: IT WORKS!!!

1 Like

https://www.lua.org/manual/5.1/manual.html#pdf-next

next (table [, index])
Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table. next returns the next index of the table and its associated value. When called with nil as its second argument, next returns an initial index and its associated value. When called with the last index, or with nil in an empty table, next returns nil. If the second argument is absent, then it is interpreted as nil. In particular, you can use next(t) to check whether a table is empty.

The order in which the indices are enumerated is not specified, even for numeric indices. (To traverse a table in numeric order, use a numerical for or the ipairs function.)

The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields.
Variant , Variant next ( table t, Variant lastKey = nil )
Returns the first key/value pair in the array. If a lastKey argument was specified then returns the next element in the array based on the key that provided. The order in which the indices are enumerated is not specified, even for numeric indices. To traverse a table in numeric order, use a numerical for loop or ipairs.

The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may, however, modify existing fields. In particular, you may clear existing fields.