如何检查两个ES2015 Map对象是否具有相同的(key, value)
对?
我们可以假设所有键和值都是原始数据类型。
解决此问题的一种方法是从中map.entries()
创建数组,然后按键对该数组进行排序。并与其他地图做同样的事情。然后遍历这两个数组来比较它们。由于排序(性能低效)以及制作这些阵列(内存效率低下),所有这些接缝都很麻烦且效率也很低。
有没有人有更好的想法?
答案 0 :(得分:21)
没有“标准”或“内置”方式来执行此操作。从概念上讲,您只需比较两个Map对象对每个键具有相同的键和值,并且没有额外的键。
为了尽可能提高比较效率,您可以进行以下优化:
Option Explicit 'Use every time will keep you from making simple mistakes...
Sub test()
Dim wb As Workbook
Dim ws As Worksheet
Dim wbSource As Workbook
Dim i As Integer
On Error GoTo ErrCatch 'add to catch errors
Set wb = Application.ThisWorkbook
Set ws = wb.Worksheets("Sheet1")
For i = 1 To 5
'## Open workbooks:
Set wbSource = Workbooks.Open("C:\Folder\" & ws.Cells(i, 2).Value & ".xlsx") 'Cells(Row,Column) 2 = "B"
'Copy from wbSource and paste in worksheet
wbSource.Sheets("Summary").Range("D13:F13").Copy Destination:=ws.Cells(i, 3) 'This syntax keeps you from having to do "Application.CutCopyMode = False" to remove the marching ants.
'Close source:
wbSource.Close False
Next i
ErrCatch:
If Err.Number > 1 Then 'test if an error was thrown
MsgBox "Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description, vbCritical
End If
End Sub
属性。如果两张地图的密钥数量不同,那么您就知道它们不能完全相同。 .size
迭代器语法来迭代密钥,这样您就不必自己构建或排序密钥数组(应该更快,更节省内存)。然后,由于for (var [key, val] of map1)
是Map中的合法值,但如果找不到密钥,它也是undefined
返回的值,我们必须通过额外{{1}来注意如果我们比较的值是.get()
。
由于具有Map对象的键和值都可以是对象本身,如果您希望对象的深度属性比较来确定相等性而不仅仅是Javascript默认使用的更简单.has()
,那么这会变得非常棘手。测试同一个对象。或者,如果您只对具有键和值基元的对象感兴趣,则可以避免这种复杂性。
对于仅测试严格值相等的函数(检查对象以查看它们是否是相同的物理对象,而不是深度属性比较),您可以执行以下所示的操作。这使用ES6语法有效地迭代地图对象,并尝试在短路时不匹配时提高性能,并在发现不匹配时立即返回undefined
。
此代码段需要Firefox 41或Chrome 49.它在Edge 25或IE 11中不起作用(可能是因为它正在使用的===
ES6语法类型的用户)。它可以通过在false
循环中使用较旧的技术在其他浏览器中工作,但由于这已经是关于ES6功能(Map对象),我们正在尝试优化实现,我选择使用最新的ES6语法。
for/of
如果你想进行深度对象比较,而不是仅仅比较它们是否在物理上是同一个对象,其中值可以是对象或数组,那么生活会变得更加复杂。
要做到这一点,您需要一个深度对象比较方法,该方法考虑以下所有因素:
for
。由于其他地方已经写了很多关于如何进行深度对象比较的内容(包括StackOverflow上的一些高度评价的答案),我认为这不是你问题的主要部分。
答案 1 :(得分:2)
如果您的Map
只有 字符串键,那么您可以使用此方法进行比较:
const mapToObj = (map) => {
let obj = Object.create(null)
for (let [k,v] of map) {
// We don’t escape the key '__proto__'
// which can cause problems on older engines
obj[k] = v
}
return obj
}
assert.deepEqual(mapToObj(myMap), myExpectedObj)
注意: deepEqual
是许多测试套件的一部分,如果没有,您可以使用lodash / underscore等效项。任何进行深度比较的函数都可以。
mapToObj
功能由http://exploringjs.com/es6/ch_maps-sets.html
答案 2 :(得分:0)
以上内容不适用于Map<string, object>
,因为以下行将无法正确评估两个对象:
if (testVal !== val || (testVal === undefined && !map2.has(key))) {
以下版本通过使用JSON.stringify()进行比较,扩展了Map<string, object>
的功能
function compareMaps(map1, map2) {
var testVal;
if (map1.size !== map2.size) {
return false;
}
for (var [key, val] of map1) {
testVal = map2.get(key);
// in cases of an undefined value, make sure the key
// actually exists on the object so there are no false positives
if (JSON.stringify(testVal) !== JSON.stringify(val) || (testVal === undefined && !map2.has(key))) {
return false;
}
}
return true;
}
答案 3 :(得分:-2)
请注意@ jfriend00提出的解决方案在打字稿ES2016中不起作用。请参阅以获得正确答案:iteration over a typescript map failing