Lua:处理文本输出的所有排列并返回替代文本

时间:2016-11-27 16:53:11

标签: lua permutation

很久以前我就这个特殊的Lua代码寻求帮助,而且它很好用。现在我正在寻求对其进行更改,而且我不确定我是否采取了正确的方式。

首先,在我玩的MUD上,我们有几个可以为设备项添加前缀的标志。它们是:(K)(M)(I)(G)(H)。无论实际存在哪些标志,它们总是以该顺序出现。例如:

(K)(M)(G)(H)
(M)(H)
(K)(I)(G)

等等。我所使用的代码只需采用上述组合,并将其分别更改为KMGHMHKIG。我现在要做的是匹配任何字母组合,并将它们括在括号内,以便[KMGH]等等。

for i = 1, #TriggerStyleRuns do

    TSRt = TriggerStyleRuns[i].text
    if string.match(TSRt,"(K)") or string.match(TSRt,"(I)") or string.match(TSRt,"(M)") or string.match(TSRt, "(G)") or string.match(TSRt, "(H)") then
        TriggerStyleRuns[i].text = string.gsub(TSRt,"%%((%%w)%%)","%%1")
    end
end

使用上面的代码,我可以设想我的计划发生的唯一方法是展望每个组合,但我真的不想有几行

if string.match(TriggerStyleRuns[i].text, "(K)") and string.match(TriggerStyelRuns[i+1].text, "(M)" and...

因为虽然我可以做到,但还有很多额外的工作。是否有更简单的方法来处理它们并确保找到的第一个元素在开头收到[,找到的最后一个元素收到]

添加奖励:我想从中删除(I)并使用它为括号着色,这需要我在第一个元素之前插入table.insert并插入最后一个元素之后。有关添加的参考,请参阅下面的TriggerStyleRuns表的样式:

TriggerStyleRuns = {
  {"backcolour"=0,"text"="( 7) ", "length"=5, "style"=1, "textcolour"=16777215}, 
  {"backcolour"=0,"text"="(K)", "length"=3, "style"=1, "textcolour"=255},
  {"backcolour"=0, "text"="(M)", "length"=3, "style"=1, "textcolour"=16711680},
  {"backcolour"=0, "text"="(G)", "length"=3, "style"=1, "textcolour"=16777215},
  {"backcolour"=0, "text"="(H) ", "length"=4, "style"=1, "textcolour"=16776960},
  {"backcolour"=0, "text"="a ", "length"=2, "style"=0, "textcolour"=12632256},
  {"backcolour"=0, "text"="Bag of ", "length"=7, "style"=1, "textcolour"=65535},
  {"backcolour"=0, "text"="Aardwolf", "length"=8, "style"=1, "textcolour"=255},
  {"backcolour"=0, "text"=" ", "length"=1, "style"=0, "textcolour"=12632256},
  {"backcolour"=0, "text"="(", "length"=1, "style"=1, "textcolour"=16777215},
  {"backcolour"=0, "text"="72", "length"=2, "style"=1, "textcolour"=65280},
 {"backcolour"=0, "text"=")", "length"=1, "style"=1, "textcolour"=16777215}
}

指数的数量可以改变,但我主要关注的是如上所述的旗帜。

修改
for循环遍历TriggerStyleRuns表。上面举例说明了一个例子。如上所述,索引的数量可以改变,这包括标志的数量。例如,如果(K)标志不存在,则在上表中,第二个索引将改为(M)而不是(K)。基本上,我需要遍历表,拉动所有标志匹配,更改这些索引中的文本,并在第一个标志之前的位置和刚刚之后的位置创建一个新标记。例如,上面的表格在完成后会如下所示:

TriggerStyleRuns = {
  {"backcolour"=0,"text"="( 7) ", "length"=5, "style"=1, "textcolour"=16777215}, 
  {"backcolour"=0,"text"="[", "length"=1, "style"=1, "textcolour"=1234567},
  {"backcolour"=0,"text"="K","length"="1", "style"=1, "textcolour"=255}, 
  {"backcolour"=0, "text"="M", "length"=3, "style"=1, "textcolour"=16711680},
  {"backcolour"=0, "text"="G", "length"=3, "style"=1, "textcolour"=16777215},
  {"backcolour"=0, "text"="H ", "length"=4, "style"=1, "textcolour"=16776960},
  {"backcolour"=0,"text"="]", "length"=1, "style"=1, "textcolour"=1234567},
  {"backcolour"=0, "text"="a ", "length"=2, "style"=0, "textcolour"=12632256},
  {"backcolour"=0, "text"="Bag of ", "length"=7, "style"=1, "textcolour"=65535},
  {"backcolour"=0, "text"="Aardwolf", "length"=8, "style"=1, "textcolour"=255},
  {"backcolour"=0, "text"=" ", "length"=1, "style"=0, "textcolour"=12632256},
  {"backcolour"=0, "text"="(", "length"=1, "style"=1, "textcolour"=16777215},
  {"backcolour"=0, "text"="72", "length"=2, "style"=1, "textcolour"=65280},
  {"backcolour"=0, "text"=")", "length"=1, "style"=1, "textcolour"=16777215}
}

1 个答案:

答案 0 :(得分:1)

我并没有真正关注你的描述,但根据我的理解,你想要做的是,给定这些字母的任意顺序,按照指定的顺序返回它们,用方括号括起来。这是一个选择:

function orderOptions( str )
    local letters = { k = '', m = '', i = '', g = '', h = '' }
    str:gsub( '%((.)%)', function( letter )
        letters[letter] = letter
    end )
    return '[' .. letters.k .. letters.m .. letters.i .. letters.g .. letters.h .. ']'
end

但是有什么问题,假设他们已经按照正确的顺序:

for i = 1, #TriggerStyleRuns do

    TSRt = TriggerStyleRuns[i].text
    if string.match(TSRt,"(K)") or string.match(TSRt,"(I)") or string.match(TSRt,"(M)") or string.match(TSRt, "(G)") or string.match(TSRt, "(H)") then
        TriggerStyleRuns[i].text = string.gsub(TSRt,"%%((%%w)%%)","%%1")
    end
    TriggerStyleRuns[i].text = '[' .. TriggerStyleRuns[i].txt .. ']'
end

修改

要从"(K)(M)(G)"等格式中取出文字,我会这样做:

-- Assuming 'flags' is the specific string
local str = '['
flags:gsub( '%((.)%)', function( flag )
    str = str .. flag
end )
str = str .. ']'

编辑2:

阅读完更新的说明后,我对你的目标有了更好的了解。看起来这样做的最好方法似乎是事先,但如果你这样做是困难的话,我想我已经有了一个想法。

因为看起来你正在修改它们所在的表(而不是创建一个新表),所以它会使事情变得复杂一些,但仍然可行。

local flags = { K = true, M = true, G = true, H = true }

TriggerStyleRuns = {
  {backcolour=0, text="( 7) ", length=5, style=1, textcolour=16777215}, 
  {backcolour=0, text="(K)", length=3, style=1, textcolour=255},
  {backcolour=0, text="(M)", length=3, style=1, textcolour=16711680},
  {backcolour=0, text="(G)", length=3, style=1, textcolour=16777215},
  {backcolour=0, text="(H) ", length=4, style=1, textcolour=16776960},
  {backcolour=0, text="a ", length=2, style=0, textcolour=12632256},
  {backcolour=0, text="Bag of ", length=7, style=1, textcolour=65535},
  {backcolour=0, text="Aardwolf", length=8, style=1, textcolour=255},
  {backcolour=0, text=" ", length=1, style=0, textcolour=12632256},
  {backcolour=0, text="(", length=1, style=1, textcolour=16777215},
  {backcolour=0, text="72", length=2, style=1, textcolour=65280},
  {backcolour=0, text=")", length=1, style=1, textcolour=16777215}
}

local function defaultText( str )
    return {backcolour=0,text=str, length=#str, style=1, textcolour=1234567}
end

local matchStarted -- nil
local i = 0
-- Can't use for loop because we're inserting elements into the same table
while matchStarted ~= false do
    i = i + 1
    local text = TriggerStyleRuns[i].text:match( '%((.)%)' )
    if flags[text] then
        if not matchStarted then
            matchStarted = true
            table.insert( TriggerStyleRuns, i, defaultText( '[' ) )
            i = i + 1 -- Don't want to process a letter twice
        end
        TriggerStyleRuns[i].text = text
        TriggerStyleRuns[i].length = #text
    elseif matchStarted then
        matchStarted = false
        table.insert( TriggerStyleRuns, i, defaultText( ']' ) )
    end
end