假设我有两个具有唯一ID的对象列表和一个确定其顺序的属性,我如何有效地获取delta索引(插入了哪些索引,哪些已删除,哪些被移动)?
输入示例:
let before: [(id: String, timestamp: String)] = [
("A", "2015-06-04T12:38:09Z"),
("B", "2015-06-04T10:12:45Z"),
("C", "2015-06-04T08:39:55Z"),
("D", "2015-06-03T23:58:32Z"),
("E", "2015-06-01T00:05:51Z"),
]
let after: [(id: String, timestamp: String)] = [
("F", "2015-06-04T16:13:01Z"),
("C", "2015-06-04T15:10:29Z"),
("A", "2015-06-04T12:38:09Z"),
("B", "2015-06-04T10:12:45Z"),
]
let delta = deltaFn(before, after)
Run Code Online (Sandbox Code Playgroud)
以上是可视化的:
BEFORE AFTER
+-------+----+----------------------+ +-------+----+----------------------+
| index | id | timestamp | | index | id | timestamp |
+-------+----+----------------------+ +-------+----+----------------------+
| 0 | A | 2015-06-04T12:38:09Z | | 0 | F | 2015-06-04T16:13:01Z |
| 1 | B | 2015-06-04T10:12:45Z | | 1 | C | 2015-06-04T15:10:29Z |
| 2 | C | 2015-06-04T08:39:55Z | | 2 | A | 2015-06-04T12:38:09Z |
| 3 | D | 2015-06-03T23:58:32Z | | 3 | B | 2015-06-04T10:12:45Z |
| 4 | E | 2015-06-01T00:05:51Z | | - | | |
+-------+----+----------------------+ +-------+----+----------------------+
Run Code Online (Sandbox Code Playgroud)
预期结果(delta):
Inserted indexes: [0]
Deleted indexes: [3, 4]
Moved indexes: [(from: 0, to: 2), (from: 1, to: 3), (from: 2, to: 1)]
Run Code Online (Sandbox Code Playgroud)
ami*_*mit 17
它可以通过使用2个映射来解决,这些映射从每个元素的ID映射到其索引,并进行比较.
时间复杂度是哈希映射的O(n)和基于树的映射的O(nlogn).
伪代码:
map1 = empty map
map2 = empty map
for each element x with index i in before:
map1.insert(x,i)
for each element x with index i in after:
map2.insert(x,i)
//find moved and deleted:
for each key x in map1:
id1 = map1.get(x)
id2 = map2.get(x)
if id2 == nil:
add id1 to "deleted indexes"
else if id1 != id2:
add (id1,id2) to "moved indexes"
map2.delete(x)
//find new indexes:
for each key x in map2:
add map2.get(x) to "inserted indexes"
Run Code Online (Sandbox Code Playgroud)
编辑 :(建议在评论中)
O(min{m,n})在基于树的映射的情况下,您可以最小化内存输出和时间,两个列表的大小O(max{m,n}log(min{m,n}))在哪里m,n,通过仅映射最小的列表,然后迭代数组(未映射)而不是映射.
map = empty map
for each element x with index i in smaller list:
map.insert(x,i)
for each element x with index i1 in larger list:
i2 = map.get(x)
if i2:
if i1 != i2:
add (i2, i1) to "moved indexes" if smaller list is before
add (i1, i2) to "moved indexes" if smaller list is after
map.delete(x)
else:
add i1 to "inserted indexes" if smaller list is before
add i1 to "deleted indexes" if smaller list is after
// Find new indexes:
for each key x in map:
add map.get(x) to "deleted indexes" if smaller list is before
add map.get(x) to "inserted indexes" if smaller list is after
Run Code Online (Sandbox Code Playgroud)