lua中,in pairs的循环的顺序问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lua中,in pairs的循环的顺序问题相关的知识,希望对你有一定的参考价值。
t = a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9
str = ""
for i,v in pairs(t) do
str = str..v..","
end
print(str)
输出是
1,3,2,5,4,7,6,9,8,
怎么才能让他输出1,2,3,4,5,6,7,8,9,啊?主要是我希望他输出的列顺序与原表中的列顺序相同
额..这已经是简化版本了,这是一个二维或者三维的table,因为多个数组使用的是一个函数来进行数组输出的功能,所以输出的函数中包含有获取元素中的列名的功能。可是输出之后就是每行数据都是这样的效果。
function player_tab_create(player_tab,number) --建立player表
for i = 1,number,1 do
table.insert(player_tab,id = table.getn(player_tab)+1 ,w_times = 0 ,l_times = 0 ,w_weight = 1,pexp = 0,bexp = 0,lv = 1,groupid = 1)
end
return player_tab
end
function out_tab(tab,lnlist) --输出二维数组
local temp =
for _,sub in pairs(tab) do --获得列名
for k,v in pairs(sub) do
temp[k] = 1
end
end
if lnlist ~= nil then
temp = lnlist
end
local str
for i = 1, table.getn(tab), 1 do
str = ""
for k,v in pairs(temp) do
if tab[i][k] == nil then
the_vaule = -1
else
the_vaule = tab[i][k]
str = str..k.." =\t "..the_vaule..",\t"
end
end
out(str)
end
end
t=1,2,3,4,5,6,7,8,9--必须是这样的table,元素必须要要用table.insert插入,用ipairs遍历,这种table相当于t[1]=1,t[2]=2...t[9]=9,如果后面有个t[11]=11,那么用ipairs就遍历不到。原因是table里面分两部分,数组和hash表,t[1],t[2]等连续的是相当于数组部分,不连续的索引都放hash表里了,顺序不一定。
str = ""
for i,v in ipairs(t) do
str = str..v..","
end
print(str)追问
谢谢回答,是这样的,我现在的问题是要保持列名的顺序,里面的值很有可能是没有顺序的,所以直接按值排序是不行的,代码我放在了问题补充了,麻烦在看下呗...
-------借个地方,问题补充放不下了-------
在输出了本来想用lnlist来存放一个数组来存放输出顺序,可是in pairs输出的还是无序的
用下面这个
function out_tab(tab,lnlist) --输出二维数组
local keys = lnlist or
if lnlist == nil then
local temp =
for _,sub in pairs(tab) do --获得列名
for k,v in pairs(sub) do
temp[k] = 1
end
end
for k,v in pairs(temp) do
table.insert(keys,k)
end
end
local str
for i = 1, table.getn(tab), 1 do
str = ""
for _,key in ipairs(keys) do
if tab[i][key] == nil then
the_vaule = -1
else
the_vaule = tab[i][key]
str = str..key.." =\t "..the_vaule..",\t"
end
end
out(str)
end
end
--------------------------------------
--这么调用
t =
player_tab_create(t,10)
out_tab(t,"id","w_times","l_times","w_weight","pexp","bexp","lv","groupid")
只有按照从1开始的自然数排列的表才能按顺序输出 否则就没办法了
所以我们这里要创建一个表,用来做key的排序,再根据这个表输出原来的顺序
key =
for i in pairs(t) do
table.insert(key,i)
end
table.sort(key)
for i,v in ipairs(key) do
print(t[v])
end
-----------以上是按照key的顺序排列------------
如果要按照值的排列的话 一个道理
key =
for i in pairs(t) do
table.insert(key,i)
end
table.sort(key,function(v1,v2) return t[v1] < t[v2] end)
for i,v in ipairs(key) do
print(t[v])
end
不过 如果按照你给的例子来说 按值排列和按key排列是看不出结果的差异追问
谢谢回答,是这样的,我现在的问题是要保持列名的顺序,里面的值很有可能是没有顺序的,所以直接按值排序是不行的,代码我放在了问题补充了,麻烦在看下呗...
按key排序的话也不成,因为key也不是有序的...而且因为多维的关系,用key输出的时候可能也会有问题
“for (... in ...)”循环中的元素顺序
【中文标题】“for (... in ...)”循环中的元素顺序【英文标题】:Elements order in a "for (… in …)" loop 【发布时间】:2010-09-21 19:07:24 【问题描述】:Javascript 中的“for...in”循环是否按照声明的顺序遍历哈希表/元素?是否有浏览器不按顺序执行? 我希望使用的对象将被声明一次并且永远不会被修改。
假设我有:
var myObject = A: "Hello", B: "World" ;
我进一步使用它们:
for (var item in myObject) alert(item + " : " + myObject[item]);
在大多数体面的浏览器中,我可以期望 'A : "Hello"' 总是出现在 'B : "World"' 之前吗?
【问题讨论】:
因为他们只会测试潜在浏览器和变体的子集。更不用说任何未来的浏览器了。假设一个不失败的测试提供任何具体的证据是完全错误的。 我怀疑我自己有限的 javascript 能力会比 SO 人群更好。除了谁知道那里潜伏着什么奇怪的浏览器吗?您可以在答案中看到 GChrome 确实有一个错误,这在我的简单示例中并不明显。 Does JavaScript Guarantee Object Property Order? 的可能重复项 也相关:Does ES6 introduce a well-defined order of enumeration for object properties? 这能回答你的问题吗? Does ES6 introduce a well-defined order of enumeration for object properties? 【参考方案1】:Quoting John Resig:
目前所有主流浏览器都按顺序循环遍历对象的属性 他们被定义了。 Chrome 也这样做,除了几个案例。 [...] ECMAScript 规范明确未定义此行为。 在 ECMA-262 中,第 12.6.4 节:
枚举属性的机制...取决于实现。
但是,规范与实现完全不同。所有现代实现 ECMAScript 按照定义的顺序遍历对象属性。 因此,Chrome 团队认为这是一个错误,并将对其进行修复。
所有浏览器都尊重定义顺序 with the exception of Chrome 和 Opera,它们对每个非数字属性名称都执行此操作。在这两个浏览器中,属性被按顺序拉到第一个非数字属性之前(这与它们如何实现数组有关)。 Object.keys
的顺序也相同。
这个例子应该清楚会发生什么:
var obj =
"first":"first",
"2":"2",
"34":"34",
"1":"1",
"second":"second"
;
for (var i in obj) console.log(i); ;
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"
这方面的技术细节不如它随时可能改变的事实重要。不要指望事情会保持这种状态。
简而言之:如果顺序对您很重要,请使用数组。
【讨论】:
并非如此。 Chrome 没有实现与其他浏览器相同的顺序:code.google.com/p/v8/issues/detail?id=164 “如果顺序对您很重要,请使用数组”:当您使用 JSON 时会怎样? @HM2K,同样的事情,规范说“一个对象是零个或多个名称/值对的无序集合。” JSON 不是 JavaScript:服务器不需要(也可能不会)尊重您处理它的顺序。 Firefox,因为它的 21 版本似乎不再尊重插入顺序。 这个答案在 ES2015 中是错误的。【参考方案2】:一年后再碰这个……
现在是2012,各大浏览器仍然不同:
function lineate(obj)
var arr = [], i;
for (i in obj) arr.push([i,obj[i]].join(':'));
console.log(arr);
var obj = a:1, b:2, c:3, "123":'xyz' ;
/* log1 */ lineate(obj);
obj.a = 4;
/* log2 */ lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */ lineate(obj);
gist 或 test in current browser
Safari 5、Firefox 14
["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]
Chrome 21、Opera 12、Node 0.6、Firefox 27
["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]
IE9
[123:xyz,a:1,b:2,c:3]
[123:xyz,a:4,b:2,c:3]
[123:xyz,a:4,b:2,c:3]
【讨论】:
这里有什么问题?正如规范所说,它是键/值对的无序列表。 nickf:实现是正确的,因为它们按照规范所说的那样做。我想每个人都同意 javascript 规范是......好吧,我不想使用“错误”这个词,“非常愚蠢和烦人”怎么样? :P @boxed:将对象视为哈希映射(表/其他)。在大多数语言(Java、Python 等)中,这些类型的数据结构都没有排序。因此,这在 JavaScript 中也是如此也就不足为奇了,它当然不会使规范错误或愚蠢。 老实说,我不明白这个答案的意义(对不起)。属性迭代的顺序是一个实现细节,并且浏览器使用不同的 JavaScript 引擎,因此预计顺序会有所不同。这不会改变。 在最先进的实现中,由于由真实数组支持,您将按数值顺序接收整数属性,并且由于隐藏的类/形状公式,将按插入顺序接收命名属性。可能会有所不同的是,它们是先列出整数属性还是先列出命名属性。delete
的添加很有趣,因为至少在 V8 中,它会立即导致对象被哈希表备份。但是,V8 中的哈希表以插入顺序存储。这里最有趣的结果是 IE,我想知道他们做了什么样的丑陋来实现它......【参考方案3】:
来自ECMAScript Language Specification,第 12.6.4 节(在for .. in
循环上):
枚举属性的机制取决于实现。枚举顺序由对象定义。
以及第 4.3.3 节(“对象”的定义):
它是一个无序的属性集合,每个属性都包含一个原始值、对象或函数。存储在对象属性中的函数称为方法。
我猜这意味着您不能依赖在 JavaScript 实现中以一致的顺序枚举的属性。 (无论如何,依赖于语言的特定实现细节都是不好的风格。)
如果您想定义您的订单,您将需要实现一些定义它的东西,例如在使用它访问对象之前排序的键数组。
【讨论】:
【参考方案4】:for/in 枚举的对象元素是没有设置 DontEnum 标志的属性。 ECMAScript,又名 Javascript,标准明确指出“对象是属性的无序集合”(参见 http://www.mozilla.org/js/language/E262-3.pdf 第 8.6 节)。
假设所有 Javascript 实现都将按声明顺序进行枚举,这将不符合标准(即安全)。
【讨论】:
这就是他问这个问题的原因,而不是仅仅假设:p【参考方案5】:在删除属性方面,迭代顺序也很混乱,但在这种情况下仅限于 IE。
var obj = ;
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';
// IE allows the value to be deleted...
delete obj.b;
// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj)
alert(obj[p]); // in IE, will be a, bb, then c;
// not a, c, then bb as for FF/Chrome/Opera/Safari
如果http://code.google.com/p/v8/issues/detail?id=164 的讨论有任何迹象,那么更改规范以修复迭代顺序的愿望似乎在开发人员中很受欢迎。
【讨论】:
【参考方案6】:在 IE6 中,不保证顺序。
【讨论】:
嗯,我的意思是...,它是 IE6。【参考方案7】:订单不可信。 Opera 和 Chrome 都返回无序的属性列表。
<script type="text/javascript">
var username = "14719":"A","648":"B","15185":"C";
for (var i in username)
window.alert(i + ' => ' + username[i]);
</script>
上面的代码在 Opera 中显示了 B、A、C,在 Chrome 中显示了 C、A、B。
【讨论】:
【参考方案8】:这本身并没有回答问题,而是为基本问题提供了解决方案。
假设您不能依赖顺序来保存,为什么不使用具有键和值作为属性的对象数组?
var myArray = [
'key' : 'key1'
'value' : 0
,
'key' : 'key2',
'value' : 1
// ...
];
现在,由您来确保密钥是唯一的(假设这对您也很重要)。同样,直接寻址也发生了变化,for (...in...)
现在将索引返回为“键”。
> console.log(myArray[0].key);
key1
> for (let index in myArray) console.log(myArray[index].value);
0
1
请参阅CodePen 上 JDQ (@JDQ) 的 Pen for (...in...) addressing in order。
【讨论】:
【参考方案9】:正如其他答案所述,不,不能保证顺序。
如果你想按顺序迭代,你可以这样做:
let keys = Object.keys(myObject);
for (let key of keys.sort())
let value = myObject[key];
// Do what you want with key and value
请注意,就性能而言,这并不是最优的,但是当您想要一个漂亮的字母显示时,这就是价格。
【讨论】:
以上是关于lua中,in pairs的循环的顺序问题的主要内容,如果未能解决你的问题,请参考以下文章
lua中的泛型for用法: for i, v in talbe do....end
无限“for i,v in pairs(table) do”循环?