0

The SciTE editor comes with embedded Lua scripting engine having access to the text buffer of the editor. This makes it possible to extend SciTE's functionality with tools programmed in Lua and started from the Tools Menu. One such tool available from here:

http://lua-users.org/wiki/SciteSortSelection

is a tool for sorting of selected lines in alphabetical order. Annoying for me was/is that it doesn't sort lines containing numbers in their numerical order but like this:

    1
  111
    2
  222
    3
  333

where I would rather expect:

    1
    2
    3
  111
  222
  333

Google and Co. are not of much help here as there is to my knowledge no solution to this problem available yet online. It is also not that easy to find and deeply understand the Lua documentation for table.sort(). So the question for a knowledgeable Lua programmer would be, what is the best way to patch the existing Lua script code, so that numbers (and also lines with text in case of leading spaces) become sorted as expected and the Lua code for this task runs so fast, that even sorting of huge files (50 MByte and more) won't take much time?

4

2 回答 2

1

你的期望是错误的。您说该算法应该按字母顺序对文本进行排序,而这正是它的作用。

对于 Lua,“11”小于“2”。我想你会同意“aa”应该出现在“b”之前,这几乎是一回事。

如果你想改变文本的排序方式,你必须提供你自己的函数。

Lua 参考手册说:

table.sort (list [, comp])

按给定顺序对列表元素进行就地排序,从 list[1] 到 list[#list]。如果给出了 comp,那么它必须是一个函数,它接收两个列表元素,并在第一个元素必须在最终顺序中的第二个元素之前返回 true(因此,在排序之后,i < j 意味着不是 comp(list[j ],列表[i]))。如果未给出 comp,则使用标准 Lua 运算符 < 代替。

请注意,comp 函数必须对列表中的元素定义严格的偏序;也就是说,它必须是不对称的和传递的。否则,可能无法进行有效排序。

排序算法不稳定:给定顺序认为相等的元素可能会因排序而改变它们的相对位置。

所以你可以自由地实现你自己的 comp 函数来改变排序。

默认情况下table.sort(list)按升序排序列表。要使其按降序排序,请调用:

table.sort(list, function(a,b) return a > b end)

如果你想以不同的方式对待数字,你可以这样做:

t = {"111", "11", "3", "2", "a", "b"}

local function myCompare(a,b)
    local a_number = tonumber(a)
    local b_number = tonumber(b)
    if a_number and b_number then
       return a_number < b_number
    end
end

table.sort(t, myCompare)

for i,v in ipairs(t) do
    print(v)
end

这会给你输出

2
3
11
111
a
b

当然,这只是一个快速简单的例子。更好的实现取决于您。

于 2017-04-01T09:01:31.440 回答
1

下面是我最终想出的。这肯定是一个快速而肮脏的解决方案,可以减慢已经很慢的速度

(与 jEdit [Plugins]->[Text Tools]->[Sort Lines] 或 bash 命令行 'sort -g' 相比)

对大量文本行缓冲区进行排序的过程,但至少可以使用并按预期工作。为了完整起见,我的 Lua Startup Script for SciTE 中当前存在的整个代码部分:

-- =============================================================================
-- Sort Selected Lines (available in MENU -> Tools):
-- -----------------------------------------------------------
-- Specify in .SciTEUser.properties:
--     command.name.2.*=# Sort Selected Lines    '
--     command.subsystem.2.*=3
--     command.mode.2.*=savebefore:no
--     command.2.*=SortSelectedLines
--     # command.shortcut.2.*=Ctrl+2 # Ctrl+2 is DEFAULT for command.2.*

function lines(str)
  local t = {}
  local i, lstr = 1, #str
  while i <= lstr do
    local x, y = string.find(str, "\r?\n", i)
    if x then t[#t + 1] = string.sub(str, i, x - 1)
    else break
    end
    i = y + 1
  end
  if i <= lstr then t[#t + 1] = string.sub(str, i) end
  return t
end

-- It was an annoying for me that using table.sort(buffer) in Lua  
-- didn't sort numbers with leading spaces in their numerical order. 
-- Using following comparison function helps to avoid that problem: 
function compare(a,b)
  return a:gsub(" ", "0") < b:gsub(" ", "0")
-- If 'compare' is not used ( table.sort(buf) )
-- Lua uses implicit for sorting (see Lua tutorial): 
--   return a < b
-- so changing the provided return statement to this above
-- would be enough to restore sorting to how it was before 
end

function SortSelectedLines()
  local sel = editor:GetSelText()
  if #sel == 0 then return end
  local eol = string.match(sel, "\n$")
  local buf = lines(sel)
  table.sort(buf, compare)
--table.foreach (buf, print) --used for debugging
  local out = table.concat(buf, "\n")
  if eol then out = out.."\n" end
  editor:ReplaceSel(out)
end

--  ---------
-- :Sort Selected Lines
-- -----------------------------------------------------------------------------
于 2017-04-01T09:08:34.150 回答