Pairs() not iterating through dictionary in order

Ipairs will print it inorder.

E

It does not loop through dictionaries in order. Use an array instead if you want it to iterate in order.

Yeah I already said can’t use ipairs cause it causes unexpected results

though if you don’t want to use ipairs you can do a numeric for loop

I actually have two dictionaries the first one runs just fine but the second one seems to not run in order…

Dictionaries aren’t ordered the same way normal tables are ordered.

local table = {1, 3, 2}

for i,v in pairs(table) do
   print(i, v)
end
-- 1, 1
-- 2, 3
-- 3, 2

You have a dictionary. It is a dictionary instead of a normal table because you’re indexing it my decimals as well as numbers. Therefore, the order is ignored. Here is another method you could try for saving that data:

local table = {
      {0, CFrame.new(0,0,0)},
      {0.2, CFrame.new(0,0,1)},
      {1, CFrame.new(1,0,0)}
}

for i,v pairs(table) do
    print(i, v[1], v[2])
end
--  1, 0, CFrame(0,0,0)
-- 2, 0.2, CFrame(0,0,1)
-- 3, 1, CFrame(1,0,0)

may I see your script where it displays the two tables?

What if I can’t change the dictionary format?
Im sorry if im being difficult here but I’m creating a animation loop system, I require table formats to not be changed in the way your suggesting.

EDIT: It would be even better if I can somehow convert a dictionary into this format

oh yeah that works perfectly actually ^

The first dictionary is similar to this

local diction1 = {
    [0] = CFrame.new(0,0,0);
    [1] = CFrame.new(1,0,0)
}

basically without the 0.2, as @Maya70i suggested it isn’t treating 0.2 when iterating in order

Oh why not just put 1,2,3 etc?

Can’t it’s a math animation loop system the 0.2 is actually the keyframe time.
EDIT: Also can’t manually change the table since this is a math animation, there are a lot of values which become unpractical meaning i need a script solution

Ah, interesting… Idek if there is a way to actually do that

How are you using the table? You should be able to change it to be compatible with Maya’s solution

What if I can’t change the dictionary format?
Im sorry if im being difficult here but I’m creating a animation loop system, I require table formats to not be changed in the way your suggesting.

EDIT: It would be even better if I can somehow convert a dictionary into this format

Let’s sort the dictionary by getting all the keys and sorting those, then using this new sorted table to get the values of those keys.

local example = {
	[0] = CFrame.new(0,0,0),
	[0.2] = CFrame.new(0,0,1),
	[1] = CFrame.new(1,0,0),
	[1.5] = CFrame.new(0,1,0),
	[2] = CFrame.new(1,1,1),
}

print(example) -- the order is all weird!

local function SortDictionary(dictionary)
	local new = {}
	for key, _ in pairs(dictionary) do
		table.insert(new, key) 
	end
	table.sort(new)
	local final = {}
	for key, value in pairs(new) do
		final[key] = {value, dictionary[value]}
	end
	
	return final
end

print(SortDictionary(example)) --[[ the order is how i organized it earlier, so:
 {
[1] =  ▼  {
                       [1] = 0,
                       [2] = 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1
},
[2] =  ▼  {
                       [1] = 0.2,
                       [2] = 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1
},
[3] =  ▼  {
                       [1] = 1,
                       [2] = 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1
},
[4] =  ▼  {
                       [1] = 1.5,
                       [2] = 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1
},
[5] =  ▼  {
                       [1] = 2,
                       [2] = 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1
}

Why not just have a certain frame rate, so every bit of time, you would go to the next frame?

Can’t you just divide the indexes by 10 for the keyframes?

local t = {
   [10] = 'value',
   [2] = 'value'
}

When iterating, divide them by 10.

local t = {
   [1] = 'value',
   [0.2] = 'value'
}

I will have a look, sorry! I practically have 1000 lines of CFrame motor animations, that I converted using a plugin. It is just unpractical to format manually.

There are so many posts here that are unnecessary,

Regarding your original goal, you can do that by creating your own function to put in the for loop. I think this is known as creating an iterator

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

local dictionary = {
	[0] = 1;
	[0.2] = 2;
	[1] = 3;
}

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

Here’s some code that I wrote

Take a look at this chapter if you’re interested more about this. Programming in Lua : 7.1


Proof of this working

local dictionary = {
	[100] = 10;
	[0] = 1;
	[0.2] = 2;
	[1] = 3;
	[.5] = 4;
	[.001] = 7;
}

for i,v in floatThrough(dictionary) do
	print('index: '..i,'value: '..v)
end

image

9 Likes

That is a interesting function!
I was on that page too, seems I didn’t read well :sweat_smile:
Let me see if that works too…