Nano Hash - криптовалюты, майнинг, программирование

сбой итерации по карте машинописного текста

Я использую функцию ниже, чтобы сравнить две карты. Что интересно, код внутри цикла 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;
    }

  • в javascript он работает. 05.08.2017

Ответы:


1

Что интересно, код внутри цикла for никогда не выполняется. Я делаю действительно глупую ошибку или упускаю глубокую концепцию?

Вы упускаете тот факт, что...

for...of не работает с Map в TypeScript до ES6

Когда он нацелен на ECMAScript до ES6, компилятор 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: если мы должны ориентироваться на ECMAScript до ES6, функция forEach может быть подходящей альтернативой циклу for...of. Остерегайтесь, однако, что forEach имеет тонкие отличия от for...of (например, ранний выход, асинхронность/ожидание).

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

Вариант 2: когда мы должны ориентироваться на ECMAScript до ES6 и должны иметь точное поведение for...of, ответ Джона Вайса имеет смысл: преобразовать Map в Array и повторить Array с for...of.

Вариант 3: когда мы можем настроить таргетинг на ECMAScript ES6 или более поздней версии. используйте цикл for...of непосредственно на Map.

В сторону: Равенство карт

Если требуется равенство карт, рассмотрите every функция. Это устраняет необходимость 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);
}

Вот демонстрация функций в действии:

const map1 = new Map([["key1", "val1"], ["key2", "val2"]]);
const map2 = new Map([["key1", "val1"], ["key2", "val2"]]);
const map3 = new Map([["key2", "val2"], ["key1", "val1"]]);

console.log(areEqual(map1, map2)); // true
console.log(areEqual(map1, map3)); // false
console.log(areSetEqual(map1, map2)); // true
console.log(areSetEqual(map1, map3)); // true
05.08.2017
  • Да, я использую карту. Я распечатал карты, которые сравниваю, и вот как они выглядят: Map(5) {"gender" => "men", "category" => "D", "1" => "11", "2" => "21", "3" => "32"} и Map(5) {"gender" => "men", "category" => "D", "1" => "11", "2" => "21", "3" => "33"} 05.08.2017
  • @JohnWeisz Спасибо. Я нашел проблему. 05.08.2017
  • @ShaunLuttin forEach работает, но загадочным образом forEach продолжает выполняться даже после того, как встречает оператор return. Таким образом, оператор return внутри forEach не останавливает его. 05.08.2017
  • @quantdaddy - Нет, оператор return внутри обратного вызова forEach по существу идентичен continue в цикле, и нет прямого эквивалента break. 05.08.2017
  • @JohnWeisz В этом есть какая-то логика? Оператор return всегда предназначен для остановки выполнения блока кода, верно? 05.08.2017
  • @quantdaddy - Конечно, в этот момент вы выходите из функции обратного вызова. Поскольку функция обратного вызова вызывается для каждой итерации, выход позволит внутренней реализации forEach продолжить вызов вашего обратного вызова для следующего элемента на карте, что функционально идентично оператору continue внутри цикла. 05.08.2017
  • Таким образом, forEach не эквивалентен запуску цикла for. Я этого не знал. Каждый обратный вызов выполняется независимо в отдельном потоке? Оператор return не выполняется внутри исходного блока кода, иначе он перестанет работать. 05.08.2017
  • Невозможно остановить или разорвать цикл forEach(), кроме как выдать исключение. developer.mozilla.org/en-US/ документы/Интернет/JavaScript/Справочник/ 05.08.2017

  • 2

    Цикл for ... of может проходить через итерируемый, а Map<K, V> сам по себе не является итерируемым. Вы можете преобразовать его в итерируемый, используя метод keys, values или entries (который затем можно преобразовать в массив).

    Например, чтобы получить массив, представляющий ключи вашей карты в порядке вставки, вы можете:

    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).

    05.08.2017
  • Если я сравниваю записи двух карт, возможно, я могу использовать map2.get(key) для получения значения второй карты в каждой итерации. Позвольте мне попробовать это. 05.08.2017

  • 3

    Кажется, это работает в машинописном тексте, если я сравниваю две карты со строковым ключом и значением.

    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;
        }
    
    05.08.2017
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..