Groovy:比较两个惰性maps/jsons
Groovy: compare two lazy maps/jsons
我有两张 jsons/lazy 地图,格式如下所示。我现在需要比较它们,看看它们之间是否有任何区别。我将每组值组合在一个字符串中以便比较变得更快的原因,因为我的实际输入(即 json 消息)将非常大。
要求Json:
[["B1": 100, "B2": 200, "B3": 300, "B4": 400],["B1": 500, "B2": 600, "B3": 700, "B4": 800], ["B1": 900, "B2": 1000, "B3": 2000, "B4": 3000], ["B1": 4000, "B2": 5000, "B3": 6000, "B4": 7000]]
响应Json:
[["B1": 100, "B2": 200, "B3": 300, "B4": 400],["B1": 500, "B2": 600, "B3": 700, "B4": 800], ["B1": 900, "B2": 1000, "B3": 2000, "B4": 3000], ["B1": 4000, "B2": 5000, "B3": 6000, "B4": 7000], ["B1": 8000, "B2": 9000, "B3": 10000, "B4": 11000]]
我的代码如下所示,但不知何故我无法获得所需的结果。我无法弄清楚出了什么问题。我从响应 Json 中获取每个值并将其与 request-Json 中的任何值进行比较以查看是否存在差异。
def diffCounter = 0
Set diffSet = []
respJson.each { respJ ->
reqJson.any {
reqJ ->
if (respJ.B1+respJ.B2+respJ.B3+respJ.B4 != reqJ.B1+reqJ.B2+reqJ.B3+reqJ.B4) {
diffCounter += 1
diffSet << [
"B1" : respJ.B1,
"B2" : respJ.B2,
"B3" : respJ.B3,
"B4" : respJ.B4
]
}
}
}
println ("Difference Count: "+ diffCounter)
println ("Difference Set: "+ diffSet)
实际输出:
Difference Count: 5
Difference Set: [[B1:100, B2:200, B3:300, B4:400], [B1:500, B2:600, B3:700, B4:800], [B1:900, B2:1000, B3:2000, B4:3000], [B1:4000, B2:5000, B3:6000, B4:7000], [B1:8000, B2:9000, B3:10000, B4:11000]]
预期输出:
Difference Count: 1
Difference Set: [["B1": 8000, "B2": 9000, "B3": 10000, "B4": 11000]]
注意: 请求-json 也可能比响应-json 大,所以在这种情况下我需要存储从 request-json 获得的差异进入 diffSet.
这方面的任何 inputs/suggestions 都会有所帮助。
正如@daggett 提到的,如果您的 JSON 变得更多 nested/complicated,您将需要使用一个库来为您完成这项工作。
在纯元素列表的用例中(值可以是 concatenated/added 以形成该元素的唯一键)这样做没有问题 'manually'.
您的代码的问题在于您检查是否有任何 reqJson
条目具有 不同的 计数,对于 2+ 个不同的 reqJson
条目总是是的。
您真正想要检查的是是否有匹配的 reqJson
条目具有 相同的 计数。如果您找不到任何匹配的条目,那么您就知道该条目仅存在于 respJson
.
中
def diffCounter = 0
Set diffSet = []
respJson.each { respJ ->
def foundMatching = reqJson.any { reqJ ->
respJ.B1 + respJ.B2 + respJ.B3 + respJ.B4 == reqJ.B1 + reqJ.B2 + reqJ.B3 + reqJ.B4
}
if (!foundMatching) {
diffCounter += 1
diffSet << [
"B1" : respJ.B1,
"B2" : respJ.B2,
"B3" : respJ.B3,
"B4" : respJ.B4
]
}
}
println ("Difference Count: "+ diffCounter)
println ("Difference Set: "+ diffSet)
你提到 reqJson
可以变得比 respJson
大,在那种情况下你想在比较中切换两个数组的角色,这样你总是从更大的数组。一个技巧是先交换两个变量。
if (reqJson.size() > respJson.size()) {
(reqJson, respJson) = [respJson, reqJson]
}
注意这个算法的时间复杂度是O(m * n * 2i)
,意思是随着两个数组(m
和n
,这里是5和4), 乘以 属性 访问的计数,我们在两个元素上进行每个循环(i
两个元素,这里是 4 因为有 4 个 B
s),因为我们可能检查每个元素对于较大数组的每个元素,较小数组的一次。
所以如果数组有数万个元素长,这将变得非常慢。将其加速到 O(m * i + n * i)
的一种简单方法是:
- 从较小数组的串联 messages/added 值中创建一个集合
smallArrayKeys
- 遍历更大的数组,检查它的串联消息是否包含在
smallArrayKeys
集合中,如果不包含则它只存在于更大的数组中。
我有两张 jsons/lazy 地图,格式如下所示。我现在需要比较它们,看看它们之间是否有任何区别。我将每组值组合在一个字符串中以便比较变得更快的原因,因为我的实际输入(即 json 消息)将非常大。
要求Json:
[["B1": 100, "B2": 200, "B3": 300, "B4": 400],["B1": 500, "B2": 600, "B3": 700, "B4": 800], ["B1": 900, "B2": 1000, "B3": 2000, "B4": 3000], ["B1": 4000, "B2": 5000, "B3": 6000, "B4": 7000]]
响应Json:
[["B1": 100, "B2": 200, "B3": 300, "B4": 400],["B1": 500, "B2": 600, "B3": 700, "B4": 800], ["B1": 900, "B2": 1000, "B3": 2000, "B4": 3000], ["B1": 4000, "B2": 5000, "B3": 6000, "B4": 7000], ["B1": 8000, "B2": 9000, "B3": 10000, "B4": 11000]]
我的代码如下所示,但不知何故我无法获得所需的结果。我无法弄清楚出了什么问题。我从响应 Json 中获取每个值并将其与 request-Json 中的任何值进行比较以查看是否存在差异。
def diffCounter = 0
Set diffSet = []
respJson.each { respJ ->
reqJson.any {
reqJ ->
if (respJ.B1+respJ.B2+respJ.B3+respJ.B4 != reqJ.B1+reqJ.B2+reqJ.B3+reqJ.B4) {
diffCounter += 1
diffSet << [
"B1" : respJ.B1,
"B2" : respJ.B2,
"B3" : respJ.B3,
"B4" : respJ.B4
]
}
}
}
println ("Difference Count: "+ diffCounter)
println ("Difference Set: "+ diffSet)
实际输出:
Difference Count: 5
Difference Set: [[B1:100, B2:200, B3:300, B4:400], [B1:500, B2:600, B3:700, B4:800], [B1:900, B2:1000, B3:2000, B4:3000], [B1:4000, B2:5000, B3:6000, B4:7000], [B1:8000, B2:9000, B3:10000, B4:11000]]
预期输出:
Difference Count: 1
Difference Set: [["B1": 8000, "B2": 9000, "B3": 10000, "B4": 11000]]
注意: 请求-json 也可能比响应-json 大,所以在这种情况下我需要存储从 request-json 获得的差异进入 diffSet.
这方面的任何 inputs/suggestions 都会有所帮助。
正如@daggett 提到的,如果您的 JSON 变得更多 nested/complicated,您将需要使用一个库来为您完成这项工作。
在纯元素列表的用例中(值可以是 concatenated/added 以形成该元素的唯一键)这样做没有问题 'manually'.
您的代码的问题在于您检查是否有任何 reqJson
条目具有 不同的 计数,对于 2+ 个不同的 reqJson
条目总是是的。
您真正想要检查的是是否有匹配的 reqJson
条目具有 相同的 计数。如果您找不到任何匹配的条目,那么您就知道该条目仅存在于 respJson
.
def diffCounter = 0
Set diffSet = []
respJson.each { respJ ->
def foundMatching = reqJson.any { reqJ ->
respJ.B1 + respJ.B2 + respJ.B3 + respJ.B4 == reqJ.B1 + reqJ.B2 + reqJ.B3 + reqJ.B4
}
if (!foundMatching) {
diffCounter += 1
diffSet << [
"B1" : respJ.B1,
"B2" : respJ.B2,
"B3" : respJ.B3,
"B4" : respJ.B4
]
}
}
println ("Difference Count: "+ diffCounter)
println ("Difference Set: "+ diffSet)
你提到 reqJson
可以变得比 respJson
大,在那种情况下你想在比较中切换两个数组的角色,这样你总是从更大的数组。一个技巧是先交换两个变量。
if (reqJson.size() > respJson.size()) {
(reqJson, respJson) = [respJson, reqJson]
}
注意这个算法的时间复杂度是O(m * n * 2i)
,意思是随着两个数组(m
和n
,这里是5和4), 乘以 属性 访问的计数,我们在两个元素上进行每个循环(i
两个元素,这里是 4 因为有 4 个 B
s),因为我们可能检查每个元素对于较大数组的每个元素,较小数组的一次。
所以如果数组有数万个元素长,这将变得非常慢。将其加速到 O(m * i + n * i)
的一种简单方法是:
- 从较小数组的串联 messages/added 值中创建一个集合
smallArrayKeys
- 遍历更大的数组,检查它的串联消息是否包含在
smallArrayKeys
集合中,如果不包含则它只存在于更大的数组中。