按顺序遍历表

简介: 按顺序遍历表

一个常见的困惑

开发人员想要对表中的元素进行排序时。由于一个表中的元素没有顺序,所以如果想对这些元素排序,就不得不先把键值拷贝到一个数组中,然后再对数组进行排序。


假如我们要读取一个源文件,然后构造一个表来保存每个函数的名称及其生命所在的行数,形式如下:

lines = {
  ["luaH_set"] = 10,
  ["luaH_get"] = 24,
  ["luaH_present"] = 48,
}


现在,我们想按照字母顺序输出这些函数名。如果使用 pairs 遍历表,那么函数名会随机出现。由于这些函数名是表的键,所以我们无法直接对其进行排序。不过,如果我们把他们放到数组中,那么就可以对他们进行排序了。


首先,我们必须创建一个包含函数名的数组,然后对其排序,再最终输出结果。

a = {}
for n in pairs(lines) do a[#a + 1] = n end
table.sort(a)
for _, n in ipairs(a) do print(n) end


有些人可能会困惑,毕竟,对于 Lua 语言来说,数组也没有顺序(毕竟他们是表)。但是我们知道如何数数!因此,当我们使用有序的索引访问数组时,就实现了有序。这正是应该总是使用 ipars 而不是 pairs 来遍历数组的原因。第一个函数通过有序的键 12 等来实现有序,然而后者使用的则是天然的随机顺序(虽然大多数情况下顺序随机也无碍,但有时可能并非我们想要的)。


现在,我们已经准备好写一个按照键的顺序来遍历表的迭代器了。

function pairsByKeys (t, f)
  local a = {}
  for n in pairs(t) do                  --> 创建一个包含所有键的表
    a[#a + 1] = n
  end
  table.sort(a, f)                      --> 对列表排序
  local i = 0
  return function ()                    --> 迭代函数
    i = i +1
    return a[i], t[a[i]]                --> 返回键和值
  end
end


工厂函数 pairsByKeys 首先把键放到一个数组中,然后对数组进行排序,最后返回迭代函数。在每一步中,迭代器都会按照数组a 中的顺序返回原始表中的一个键值对。可选参数f 允许指定一种其他的排序方式。


使用这个上述函数,可以很容易得解决开始时提出的按照顺序遍历表的问题:

for name, line in pairsByKeys(lines) do
  print(name,line)
end


像通常一样,所有的复杂性都被隐藏到了迭代器中。

目录
相关文章
|
1月前
|
算法 测试技术 C#
【哈希映射】【 哈希集合】 381. O(1) 时间插入、删除和获取随机元素 - 允许重复
【哈希映射】【 哈希集合】 381. O(1) 时间插入、删除和获取随机元素 - 允许重复
|
1月前
顺序排号
顺序排号。
31 5
|
1月前
判断两个不重复的list集合是否相等 只比较元素值 不比较顺序
判断两个不重复的list集合是否相等 只比较元素值 不比较顺序
39 0
|
JSON 数据格式 Python
一日一技:包含非hashable元素的列表如何去重并保持顺序?
一日一技:包含非hashable元素的列表如何去重并保持顺序?
89 0
关于对象遍历的时候的一些排序问题
关于对象遍历的时候的一些排序问题
关于对象遍历的时候的一些排序问题
记录插入顺序用linkedHashMap
记录插入顺序用linkedHashMap
93 0
遍历表
遍历表
74 0
|
存储 分布式计算 并行计算
如何1分钟内完成遍历100T数据?
如何1分钟内完成遍历100T数据?
286 0
如何1分钟内完成遍历100T数据?
顺序线性表的插入、删除、合并
顺序线性表的插入、删除、合并 前言 插入 删除 合并
175 0