Looping through a dictionary is out of order, but is always the same order?

I have a script that automatically gives players badges based on how long they have been ingame, however for some reason the game does it out of order (which is annoying me, because I have chat announcements). The relevent code is:

local timeBadges = {
	[10] = 2124832987, --10 minutes
	[30] = 2124832988, --30 minutes
	[60] = 2124832989, --1 hour
	[120] = 2124832990, --2 hours
	[300] = 2124832991, --5 hours
	[600] = 2124832992, --10 hours
	[1440] = 2124832993, --1 day
	[4320]	= 2124832994, --3 days
	[10080]	= 2124832995 -- 1 week
}
while true do
		for i, v in pairs(playerTimes) do
			--Award badges
			for m, n in pairs(timeBadges) do
				if not badgeService:UserHasBadgeAsync(i, n) then
					if v/60 >= tonumber(m) then
						badgeService:AwardBadge(i, n)
						Chat.Announce(game.Players:GetNameFromUserIdAsync(i), n) --Custom module, don't worry about this
					end
				end
			end
		end
		wait(20)
	end

The order is always this:
image
(Image is hard to see, but it is: 10M, 10H, 24H, 1H, 2H, 5H, 30M)

Anyone know what may be causing this?

Dictionaries are key-value pairs, and are never saved in-order. You’d need to convert this dictionary into an array and sort it manually for this application
*They’re explained well under the table documentation, but in general dictionaries can’t be referenced by a numerical index since they’re not saved in that way, which is also why you can only iterate them in pairs and not ordered-pairs.

Might i know wt playerTimes stand for?

I understand that, but a couple of things make me question whether that is the cause:

  1. The dictionary is constant, and is never modified after the initilization of the script
  2. The output in the chat is always the same order

playerTimes means the player times…
Its a dictionary that holds the value of how long everyone has been in game

That’s odd, but the order they are displayed is unreliable. For this application I’d load all of the applicable values into an array and sort them before displaying them all through the module.

Dictionaries never run in order, u hav to use arrays for that.

For ur issue, i found a piece of code tht mite as well work for this problem.

local function floatThrough(array)
	local indexCache = {}
	for index in pairs(array) do -- get index's in order
		table.insert(indexCache, index)
	end
	table.sort(indexCache)

	local i = 1
	return function()
		if indexCache[i] ~= nil then
			i = i + 1;
			return indexCache[i-1], array[indexCache[i-1]];
		end
	end
end

for i,v in floatThrough(timeBadges) do
	print(i,v)
end

Note Code isn’t mine.

why not order in the way in which they get printed? you get the point right?

I ended up just putting it in a table, which I thought about earlier anyway, then using the next() thingy to get the values from the dictionary

1 Like

Or convert it into arrays:

local timeBadges = {
  {10, 2124832987}--10 minutes
  {30, 2124832988}--30 minutes
  {60, 2124832989}

this is actually a good solution

thats not how it works

what about using seconds?

local timeBadges = {
	[10*60] = 2124832987, --10 minutes
	[30*60] = 2124832988, --30 minutes
	[60*60] = 2124832989, --1 hour
	[120*60] = 2124832990, --2 hours
	[300*60] = 2124832991, --5 hours
	[600*60] = 2124832992, --10 hours
	[1440*60] = 2124832993, --1 day
	[4320*60]	= 2124832994, --3 days
	[10080*60]	= 2124832995 -- 1 week
}
local timeBadges = {
	{10 , 2124832987}; --10 minutes
	{30 , 2124832988}; --30 minutes
	{60 , 2124832989};   --1 hour
	{120 , 2124832990 };--2 hours
	{300 , 2124832991 };--5 hours
	{600 , 2124832992 };--10 hours
	{1440 , 2124832993}; --1 day
	{4320	, 2124832994 };--3 days
	{10080	, 2124832995};-- 1 week
}
while true do
	for i, v in pairs(playerTimes) do
		--Award badges
		for m, n in pairs(timeBadges) do
			if not badgeService:UserHasBadgeAsync(i, n[2]) then
				if v/60 >= tonumber(n[1]) then
pcall(function()
	badgeService:AwardBadge(i, n[2])
	Chat.Announce(game.Players:GetNameFromUserIdAsync(i), n[1])  --Custom module, don't worry about this
end) -- Just to be safe
				end
			end
		end
	end
	wait(20)
end

This may actually work