【问题标题】:How to compare modified array against original (in Lua)?如何将修改后的数组与原始数组(在 Lua 中)进行比较?
【发布时间】:2020-12-01 11:01:11
【问题描述】:

先来一点伪代码:

local array = {
    "a",
    "b",
    "c",
    "d",
    "e",
    "f",
    "g",
}

现在,创建一些数据,其中存储有关原始数组的重要信息。可能只是复制整个数组,但由于我不知道解决问题的最快方法是什么,所以我保持打开状态。


local info = createinfo(array)

现在创建一个新版本的数组,可以使用table.remove/insert() 或者只使用原始元素创建一个新数组。所以没有覆盖table.insert/remove()的恶作剧。


local array = {
    "a",
    "b",
    "d",
    "e",
    "f",
    "c",
}

找出发生了什么变化(以下规格)


local changes = calculatechanges(array, info)

我想知道什么?

  1. 什么元素被移动了? (例如"c"
  2. 删除了哪些元素? (例如"g"
  3. 我对元素移动到哪里不感兴趣。

如果可能的话,我如何找到它? 什么是最快的方法,因为我最初的问题是时间紧迫的(createchanges()calculatechanges())?

附:顺便说一句,如果这很重要,我正在使用 Lua 5.1。

编辑: 作为“改变”,我定义了以下内容: 将原始数组转换为修改后的“将 x 从索引 i 移动到 j”的最小量是多少?

另一个编辑: 可能我正在寻找 Levenshtein 距离的类似实现。但是,我需要知道,必须替换哪些元素,而不是(仅)距离。

【问题讨论】:

  • cd 已交换。那么,What Element has been moved?c 还是d
  • 这实际上是一个好问题。我将编辑我的问题以使其更加精确。我在列表中添加了更多元素,因此很明显,我想要最少的更改。
  • change 的定义是什么,如果是索引变化,那么除了 c 之外,def 也是如此。例如:"a","b","c","d" -> "a","c","b","d" 你会如何描述这种变化?以及它与"a","c","d","b" 有何不同请注意c 在这两种情况下都已“移动”。
  • @Nifim 好的,我想我现在明白了,我的问题还不清楚。作为更改,我定义了以下内容:以“将 x 从索引 i 移动到索引 j”为单位的最小移动,以将原始数组转换为修改后的版本。这是否澄清了我的问题?我希望我没有让它变得更加混乱。
  • 现在听起来您正在寻找一种计算编辑距离的方法,例如,Levenshtein distance

标签: arrays algorithm performance lua


【解决方案1】:

这是一个解决方案,我反转了数组以简化索引查找。 然后我使用 while 循环选择性地增加 a1a2 的索引。

function diff(a1, a2)

  local added = {}
  local moved = {}
  local removed = {}

  local a1IndexOf = {}
  for i, v in ipairs(a1)do
    a1IndexOf[v] = i
  end

  local a2IndexOf = {}
  for i, v in ipairs(a2)do
    a2IndexOf[v] = i
  end

  local index1 = 1
  local index2 = 1
  while(index1 <= #a1) do
    local value1 = a1[index1]
    local value2 = a2[index2]

    if value1 == value2 then
      index1 = index1 + 1
      index2 = index2 + 1

    elseif a2IndexOf[value1] == nil then   
      removed[value1] = true
      index1 = index1 + 1

    elseif moved[value1] then
      index1 = index1 + 1

    elseif moved[value2] then
      index2 = index2 + 1

    elseif a1IndexOf[value2] < a2IndexOf[value1] then
      moved[value1] = true
      index1 = index1 + 1
    else
      moved[value2] = true
      index2 = index2 + 1
    end
  end

  print("\nElements Moved:")
  for v in pairs(moved) do
    print("\t" .. v)
  end
  print("\nElements Removed:")
  for v in pairs(removed) do
    print("\t" .. v)
  end
end

一些示例输入和结果:

local array = {
  "a",
  "b",
  "c",
}

local info = {

  "a",
  "c",
  "b",
}
Elements Moved:
    c

Elements Removed:
local array = {
  "a",
  "b",
  "c",
}

local info = {

  "a",
  "c",

}
Elements Moved:

Elements Removed:
    b

【讨论】:

  • 刚刚阅读了您的代码,时间复杂度似乎与 N 成正比。这是 Levensthein 算法吗?
  • @Sewbacca 我认为这更像是一种对称差异,还包括位置的变化,不确定这种算法是否有名称
  • 必须对原始数组中的每一项进行审核,也就是说,如果我们无法在您进行更改时记录下来。 Levensthein 是 O(nm),我相信这类似于 O(2n + 2m)
  • 如果你使用{'a', 'b', 'c', 'd', 'e', 'f', 'g'}的OP样本输入-->{'a', 'b', 'd', 'e', 'f', 'c'}diff的结果是'c'已经被移动并且'g'已经被移除。但是,你不是说'd'、'e'和'f'也被移动了吗?唯一保留在其原始索引处的元素是“a”和“b”。
  • @exnihilo 根据 OP,没有。他们想要这种特定的行为
猜你喜欢
  • 1970-01-01
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 2021-05-18
  • 2015-10-05
  • 2019-04-03
相关资源
最近更新 更多