Lua:Table 操作 - 加法和减法 Key/Value 基于另一个的对 Table

Lua: Table Manipulation - Adding & Subtracting Key/Value Pairs Based on Another Table

我正在尝试使用收到的输入并根据找到的特定输入 (ID#) 构建 table。此输入还包含我需要解析的变量,我使用那些其他变量来构建完整的数据字符串。在同一个文件中,是一个应该记录项目的列表。一旦文件被接收并被 Lua 脚本完全解析,它就会按照特定的顺序发回字符串,该顺序也位于收到相同的文件。

例如:

收到输入:

Log Entries Received:
ID1 - 9:25AM - 10:15AM - Mike Stephens - 2/12/2015 - 111 Dynamo Dr.
ID2 - 8:07AM - 12:20PM - Gary Roberts - 1/23/2015 - 1212 Badger Way
ID3 - 11:46AM - 1:31PM - Trishia Major - 2/10/2015 - 325 March Manor
ID4 - 2:49PM - 3:13PM - Harry Davis - 12/21/2014 - 844 Anapolis Dr.
ID5 - 7:56AM - 8:47AM - Mary Hudson - 1/19/2015 - 9124 Royal Dr.
ID6 - 9:41AM - 4:16PM - Mark Harrison - 1/29/2015 - 583 Connecticut Rd.
ID7 - 10:25AM - 12:45PM - Jennifer Smith - 12/30/2014 - 42 Rodding Rd.
End of Log Entries

Order to be Sent:
ID3 - ID2 - ID5 - ID1 - ID7 - ID4 - ID6
End of Order

现在 ID# 按时间顺序接收... 1、2、3、4 等;直到接收到所有输入字符串。在收到的所有这些数据的末尾,是应该处理字符串的另一个列表。这包含在一个完整的文件中。

最初,我认为最好有两个独立的 table,每个都在自己独立的功能中构建和维护。第一个函数将接收队列的顺序,将 table 的键与接收到的顺序中的值 (ID#'s) 配对。这发生在下面称为 function iD_Order(log_queue) 的函数中。第二个函数将使用输入数据构建完成的字符串,在 function string_build(log_input) 中找到。我想构建第二个 table,将第二个 table 的键设置为等于在字符串中找到的 ID#,并将值设置为等于完成的字符串本身。

我遇到的问题是如何同时使用这两个函数,以便在发送下一个队列时,它会根据接收到的队列进行发送。另外,我想做到这一点,一旦整个队列成功通过,它就会完全删除两个 table,这样这个过程就可以从头开始重复。

以下是我目前根据所提供的信息以及我对最佳方法的想法。

function string_build(log_input)  -- takes input and creates strings (don't know how to build table found in this function)
    t_msg = {}
    for iD, time_In, time_Out, usr_Name, date, usr_Addr in input:gmatch("(ID%d)|(.-)|(.-)|(.-)|(.-)|(.-)") do
        finish_Str = "Operator Name: "..usr_Name.." (ID#:"..iD..") on "..date.." signed in at "..time_In.." and signed out at "..time_Out.." at "..usr_Addr.." open house location."
    end
    for k,v in pairs (t_msg) do
        t_msg.iD = finish_Str -- I strongly doubt this is correct????
    end
end

function iD_Order(log_queue) -- takes queue and puts values = order of ID#'s
    t_Queue = {}
    for iD_nmbr in log_queue:match("(ID%d)") do
        for k,v in pairs (t_Queue) do
            table.insert(t_Queue, #t_Queue, iD_nmbr)
        end
    end
end

function log(input) -- main function that receives outside input and sends it to appropriate functions
    local buffer = ""
    input = input:gsub("%s-%s", "|")
    buffer = buffer..input.."|"
    log_input = input:match("Log Entries Received:(.*)End of Log Entries")
    log_queue = input:match("Order to be Sent:(.*)End of Order")
    if log_input then
         string_build(log_input)
         buffer = buffer:sub(#log_input)
    end
    if log_queue then
         iD_Order(log_queue)
         buffer = buffer:sub(#log_queue)
    end
end

这是我不确定最佳做法的地方。作为一般编程的新手,我正在努力学习最好的 practice/mindset 来争取。我认为,让一个 table 在完全不同的功能中依赖另一个可能是不好的做法?我不确定。但是我正在考虑有另一个函数可以从 function iD_Order(log_queue) 中获取 table 并且使用 function string_build(log_input) 和 select 创建的字符串基于 iD 变量可能在删除最后的 table 时会很乱,可能会导致问题。

如果 t_Queue 的键与完成字符串中的 iD 变量匹配,我认为最好将完成的字符串直接发送到 t_Queue 中。但我很难弄清楚如何做到这一点。

感谢所有的帮助、意见和批评。

您的方法似乎正朝着正确的方向前进。 由于您的 IDs 是唯一的,并且它们是您要用来引用日志条目的值,因此将它们用作输入 table 的键是有意义的,或者作为字符串("ID1") 或数字 (1) 但数字可能更好一些。由于顺序 table 只是您的键的序列,因此以任何顺序打印都变得非常容易。

处理函数之间依赖关系的一个好方法是为日志条目定义通用格式。在某处您可能想要修改日志条目,按用户名排序等,因此将它们解析为 tables 将在字段分隔的情况下得到回报。

分离输入和输出操作

将输入和输出分开也很有帮助,您可能有多种获取日志条目的方法,以及多种输出日志条目的方法,因此请避免耦合输入和输出。

将作用域保持在本地

通常最好在函数中使用 local 变量并 return 结果,这样每次调用都不会更改全局 table。如果您想解析多个文件,这可能会导致一些意外行为。当函数退出时,局部变量消失了(除非已经 returned),所以在函数 reorder_log_entries() 中,创建的 table 都在它完成时被销毁,你调用 call再次使用它,这样您就不必担心 deleting/emptying 和 table 了。下面的代码是我将如何组织功能,但它不会 read/write 到文件。

function parse_order(log_order)
    local order = {} -- make it local to avoid clashes
    for id in log_order:gmatch("ID(%d)") do
        order[#order + 1] = tonumber(id) -- append id to table.
    end
    return order -- {3, 2, 5, 1, 7, 4, 6} in example.
end

function parse_log_entry(entry)
    local ID, time_In, time_Out, usr_Name, date, usr_Addr =
       entry:match("ID(%d) %- (.-) %- (.-) %- (.-) %- (.-) %- (.-)")
    return {id=tonumber(ID), time_in=time_In, time_out=time_Out,
        user_name=usr_Name, date=date, user_addr=usr_Addr}
end

function format_log_entry(entry)
    return "Operator Name: "..entry.user_name
       .." (ID#:"..entry.id..") on "
       ..entry.date.." signed in at "..entry.time_in
       .." and signed out at "..entry.time_out
       .." at "..entry.user_addr.." open house location."
end

input = [[Log Entries Received:
ID1 - 9:25AM - 10:15AM - Mike Stephens - 2/12/2015 - 111 Dynamo Dr.
ID2 - 8:07AM - 12:20PM - Gary Roberts - 1/23/2015 - 1212 Badger Way
ID3 - 11:46AM - 1:31PM - Trishia Major - 2/10/2015 - 325 March Manor
ID4 - 2:49PM - 3:13PM - Harry Davis - 12/21/2014 - 844 Anapolis Dr.
ID5 - 7:56AM - 8:47AM - Mary Hudson - 1/19/2015 - 9124 Royal Dr.
ID6 - 9:41AM - 4:16PM - Mark Harrison - 1/29/2015 - 583 Connecticut Rd.
ID7 - 10:25AM - 12:45PM - Jennifer Smith - 12/30/2014 - 42 Rodding Rd.
End of Log Entries

Order to be Sent:
ID3 - ID2 - ID5 - ID1 - ID7 - ID4 - ID6
End of Order]]


-- read the log entries from the input string
function reorder_log_entries(input)
    local log = {}
    local log_paragraph = input:match("Log Entries Received:(.*)End of Log Entries")
    for line in log_paragraph:gmatch("%s*([^\r\n]+)") do
       entry = parse_log_entry(line)
       log[entry.id] = entry
    end
    local order = parse_order(input:match("Order to be Sent:(.*)End of Order"))
    for _, id in ipairs(order) do
       print(format_log_entry(log[id]))
    end
end