Как реализовать Java HashMap.equals(HashMap) в JavaScript

Я пытаюсь написать функцию, которая принимает две строки и возвращает, имеют ли они одинаковую частоту букв. Предполагается, что ни одна из строк не является нулевой.

Вот моя реализация Java:

  public void addToMap(HashMap<String, Integer> map, String s){
  if(map.get(s) == null){
    map.put(s, 1);
  } else{
    map.put(s, map.get(s)+1);
  }
}

  public boolean perm(String a, String b){
    if(a.length() != b.length()){
      return false;
    }
    HashMap<String, Integer> aMap = new HashMap<>();
    HashMap<String, Integer> bMap = new HashMap<>();
    for(int i = 0; i < a.length(); i++){
      addToMap(aMap, a.substring(i,i+1));
      addToMap(bMap, b.substring(i,i+1));
    }
    return aMap.equals(bMap);
  }

Я пытаюсь воспроизвести это в JavaScript:

const addToMap = (map, s) => {
  if(map[s] == null){
    map[s] = 1;
  } else{
    map[s] = map[s]+1;
  }
}

const perm = (a,b) => {
  if(a.length != b.length){
    return false;
  }
  let aMap = new Map();
  let bMap = new Map();
  for(let i = 0; i < a.length; i++){
    addToMap(aMap, a.substring(i,i+1));
    addToMap(bMap, b.substring(i,i+1));
  }
  return aMap === bMap;
}

Я протестировал perm("abca", "bcaa") для обеих реализаций. Код Java возвращает true, что правильно. Однако функции JS возвращают false.

Есть ли способ вернуть, что две карты равны в JS, когда они имеют одинаковые ключи и значения, но в другом порядке?


person God Complex    schedule 27.06.2018    source источник
comment
Если ваш код работает, задайте его в Code Review.   -  person soufrk    schedule 27.06.2018
comment
Проблема в том, как вы сравниваете оба объекта Map() в Javascript. Я настоятельно рекомендую вам проверить это stackoverflow.com/questions/35948335/   -  person Ivan Kaloyanov    schedule 27.06.2018


Ответы (2)


Проблема с вашим кодом заключается в том, как вы сравниваете два объекта карты. В Java вы используете equels, но если вы используете ==, вы всегда получите тот же ложный результат. В js вы можете сравнить два объекта по циклу через ключи и сравнить существование и значение каждого ключа или, если короче, но с небольшими накладными расходами, просто выполните JSON.stringify(aMap)===JSON.stringify(bMap) вместо aMap==bMap

Обновление Как вы упомянули, JSON.stringify не работает. (Обычно, когда вы перебираете ключи, они идут в алфавитном порядке, но это функция, зависящая от браузера, поскольку объект в js обычно не имеет упорядоченных свойств ключ-значение).

Поэтому, когда я упоминаю, вам просто нужно сравнить две карты. Например:

const isSubMap = function(mapA, mapB) {
  for (let key in mapA) {
    if (!mapB[key] || mapA[key] !== mapB[key]) {
      return false;
    }
  }
  return true;
}

Но что касается меня, я бы пошел с другим подходом к решению этой проблемы: 1) Суммируйте коды для всех символов из строки A и строки B, а затем сравните sumA == sumB; 2) Просто создайте карту различий. Таким образом, символы из строки A будут добавлять ключ к карте со значением 1 и/или увеличивать счетчик, а символы из строки B будут уменьшать счетчик, если значение свойства больше 1, или создавать новый со значением -1 (если значение === 0, то удалить ключевое свойство из объекта). В конце проверьте, имеет ли объект нулевые свойства с помощью Object.keys(obj).length === 0;

person Romick    schedule 27.06.2018
comment
Он по-прежнему возвращает false. Это не удается: console.log(perm(abca, bcaa)); Сравниваемые строки: Map { a: 2, b: 1, c: 1 } Map { b: 1, c: 1, a: 2 } Я не понимаю, почему они проходят. - person God Complex; 29.06.2018
comment
Однако это работает, добавление этого в мой код заставит меня пройти всю строку и карту, чего я бы предпочел не делать. Я нашел решение вопроса перестановки: stackoverflow.com/questions/35948335/ Объект карты в JS просто не сравнивается. stackoverflow.com/q/37049306/7066218 Но для моей проблемы с картой JS кажется, что - person God Complex; 04.07.2018

Вот код, который я создал, который работает:

const addToMap = (map, s) => {
  if(map.has(s)){
    map.set(s, map.get(s)+1);
  } else{ map.set(s, 1);}
}

const perm = (a, b) => {
  if(a.length != b.length){ return false; }
  let aMap = new Map();
  let bMap = new Map();
  for(let i = 0; i < a.length; i++){
    addToMap(aMap, a.substring(i, i+1));
    addToMap(bMap, b.substring(i, i+1));
  }
  return aMap.toString() == bMap.toString();
}
const s1 = "abcda";
const s2 = "cdbaa";
console.log(perm(s1, s1));

Случилось так, что я использовал неправильный синтаксис для Map(). Вместо этого я использовал нотацию скобок для создания пар ключ-значение или методы Map.prototype.

См. этот пример кода:

let m = new Map();
m.set(1, "a");
m[2] = "b";
console.log(m);
//Output: Map { 1 => 'a', 2: 'b' }

У меня работают методы Map.get и Map.set.

person God Complex    schedule 28.09.2018