对打字稿地图的迭代失败

时间:2017-08-05 08:52:45

标签: javascript typescript iterator

我使用下面的功能来比较两张地图。有趣的是for循环中的代码永远不会被执行。因此,console.log(key,val)代码永远不会被执行。当然,我确保我比较的地图不是空的,并且大小相同,以强制执行for循环中的代码。我犯了一个非常愚蠢的错误,或者错过了一个深刻的概念?

private compareMaps(map1, map2) {
        var testVal;
        if (!(map1 && map2)) {
            return false;
        }
        if (map1.size !== map2.size) {
            return false;
        }
        for (var [key, val] of map1) {
            testVal = map2.get(key);
            console.log(key, val);
            if (testVal !== val || (testVal === undefined && !map2.has(key))) {
                return false;
            }
        }
        return true;
    }

3 个答案:

答案 0 :(得分:2)

  

有趣的是for循环中的代码永远不会被执行。我犯了一个非常愚蠢的错误,或者错过了一个深刻的概念?

你错过了......

这一事实

for...of在ES6

之前的TypeScript中不适用于Map

当它在ES6之前定位ECMAScript时,TypeScript编译器将for...of语句转换为for循环。

此代码:

for (var [key, val] of map) {
    console.log(key);
}

成为这段代码:

for (var _i = 0, map_1 = map; _i < map_1.length; _i++) {
    var _a = map_1[_i], key = _a[0], val = _a[1];
    console.log(key);
}

怎么办?

选项1 :当我们必须在ES6之前定位ECMAScript时,forEach函数可以替代for...of循环。请注意,forEachfor...of存在细微差别(例如,早退出,异步/等待)。

map.forEach((val, key) => { 
    console.log(key + ":" + val);
});

选项2 :当我们必须在ES6之前定位ECMAScript时,我们必须具有for...of的确切行为,answer by John Weisz才有意义:转换{{1转到Map并使用Array迭代Array

选项3 :当我们可以定位ECMAScript ES6 or later时,请直接在for...of上使用for...of循环。

旁白:地图平等

如果要求是地图平等,请考虑the every function。这需要在迭代中Map的需要,因为break会在找到第一个every时立即返回。

如果订单比较重要,请使用false,如下所示:

every

如果顺序无关紧要,那么我们希望设置相等;像这样使用function areEqual<K,V>(map1: Map<K,V>, map2: Map<K,V>) { if(!map1 || !map2) return false; const array1 = Array.from(map1.entries()); const array2 = Array.from(map2.entries()); return array1.every(([k1, v1], index) => { const [k2, v2] = array2[index]; return k1 === k2 && v1 === v2; }); }

every

以下是行动中的功能演示:

function areSetEqual<K, V>(map1: Map<K, V>, map2: Map<K, V>) { 
    if(!map1 || !map2) return false;
    const array1 = Array.from(map1.entries());
    const array2 = Array.from(map2.entries());
    return array1.length === array2.length &&
        array1.every(([k1, v1]) => map2.get(k1) === v1);
}

答案 1 :(得分:2)

for ... of循环可以通过可迭代,而Map<K, V>本身不是可迭代的。您可以使用keysvaluesentries方法将其转换为可迭代的方法(然后您可以进一步转换为数组)。

例如,要获得以插入顺序表示Map键的数组,您可以:

let keys = Array.from(map1.keys());

然后,您可以使用keys循环遍历此for ... of数组,因为数组是可迭代的:

for (var key of keys) {
    testVal = map2.get(key);
    console.log(key, val);

    if (testVal !== val || (testVal === undefined && !map2.has(key))) {
        return false;
    }
}

有趣的是,我相信它应该可以实现这一点而无需创建数组,即只使用for (let key of map1.keys()),因为.keys()本身会返回一个可迭代的,但是TypeScript似乎在处理问题时遇到了问题(至少在ES5中,没有尝试过ES6目标)。

答案 2 :(得分:1)

如果我将两个地图与字符串键和值进行比较,那么这似乎适用于打字稿。

private compareMaps(map1, map2) {
        var testVal;
        if (!(map1 && map2)) {
            return false;
        }
        if (map1.size !== map2.size) {
            return false;
        }
        for (let key of Array.from(map1.keys())) {
            let val = map1.get(key);
            testVal = map2.get(key);
            if (testVal !== val || (testVal === undefined && !map2.has(key))) {
                return false;
            }
        }
        return true;
    }