Как проверить, имеют ли две карты одинаковый ключ в JavaScript

Предположим, у вас есть два объекта карта, как проверить, совпадают ли их наборы ключей?

Например:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

в этом случае карты A и B имеют один и тот же набор ключей (который является ['x', 'y']), в то время как набор ключей C отличается, поскольку он имеет дополнительный ключ z.

Вы имеете в виду stackoverflow.com/questions/14368596/…?

SuperDJ 26.08.2018 22:06

вы не можете вызвать .keys().size() на объекте Map

Francesco Borzi 26.08.2018 22:08

@SuperDJ специфичен для Map Я не думаю, что этот вопрос одинаковый, в основном способ ответов будет другим

Koushik Chatterjee 27.08.2018 11:48

@ FrancescoBorzì, могу я спросить, почему вы приняли мой длинный и неуклюжий ответ вместо других, которые выглядят короче / чище? (Единственное, что я могу придумать, это сложность ответа, мой больше похож на самообъясняющий псевдокод)

Fabian N. 27.08.2018 12:01

потому что это наиболее понятный ответ: D

Francesco Borzi 27.08.2018 12:22
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
687
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Убедитесь, что size каждой карты одинаков, а затем переберите keys одного Map и убедитесь, что ключ существует и в другом. Использование Array.prototype.every.call означает, что создавать промежуточный массив не нужно:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

const sameKeySet = (m1, m2) => (
  m1.size === m2.size
  && Array.prototype.every.call(m1.keys(), key => m2.has(key))
);
console.info(sameKeySet(A, B));
console.info(sameKeySet(A, C));

Что ж, это выглядит определенно чище, чем у меня. Есть ли причина использовать Array.prototype вместо []. Также нельзя ли снять скобки (... && ...) с условием?

Fabian N. 26.08.2018 22:21

Использование Array.prototype.every.call означает, что нет необходимости создавать промежуточный массив, тогда как что-то вроде [...m1.keys()]было бы излишне создает новый массив из итератора. Да, было бы синтаксически правильно опустить круглые скобки, но поскольку это многострочное выражение, я думаю, что круглые скобки делают код более понятным для чтения.

CertainPerformance 26.08.2018 22:25

А, ладно, я думал о [].every.call, надеясь, что пустой массив не будет такой большой проблемой и не будет выглядеть «так страшно», как Array.prototype =) [на самом деле я только хотел сократить его до двух строк]

Fabian N. 26.08.2018 22:28
Ответ принят как подходящий

Вы можете проверить размер, а затем перебрать ключи одной карты и проверить, есть ли они и на другой.

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

function sameKeys(a, b) {
  if (a.size != b.size) {
    return false;
  }

  for (let key in a.keys()) {
    if (!b.has(key)) {
      return false;
    }
  }

  return true;
}

console.info(sameKeys(A, B));
console.info(sameKeys(A, C));

Вы можете преобразовать ключи Map в массив, расширив итератор, возвращаемый методом keys():

const aKeys = [...A.keys()];

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

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

const aKeys = [...A.keys()];
const bKeys = [...B.keys()];
const cKeys = [...C.keys()];

console.info(aKeys.sort().toString() == bKeys.sort().toString());
console.info(aKeys.sort().toString() == cKeys.sort().toString());
console.info(bKeys.sort().toString() == cKeys.sort().toString());

В основном вам нужно проверить две вещи:

  1. Размер обеих карт, если они не равны, просто верните false.
  2. Если размер такой же, как и проверьте, все ли ключи map1 присутствуют в map2, если они есть, то верните true, иначе верните false.

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

const D = new Map();
C.set('x', 121);
C.set('z', 232);


function isSame(a,b){
  if (a.size != b.size)
    return false;
 for(const [key, value] of a.entries()){
    if (!b.has(key))
      return false;
  }
  return true;
}
console.info(isSame(A,B));
console.info(isSame(A,C));
console.info(isSame(A,D));

Вы можете проверить размер и взять прототип has и вторую карту как thisArg для проверки всех ключей с помощью Array#some.

Это работает для любых типов, поскольку не изменяет тип ключей.

const
    compare = (a, b) => a.size === b.size && [...a.keys()].some(Map.prototype.has, b),
    a = new Map([['x', 123], ['y', 345]]);
    b = new Map([['y', 567], ['x', 789]]);
    c = new Map([['x', 121], ['y', 232], ['z', 434]]);

console.info(compare(a, b));
console.info(compare(a, c));

Вы можете построить новый Map с обоими их записями, а затем сравнить размер. В любом случае вам нужно проверить размер их обоих, и если он такой же, то только вы должны продолжить.

map1.size.size===map2.size &&

new Map([...map1, ...map2])).size===map1.size// или map2.size

Создадим рабочий пример:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

let compareMap = (m1, m2) => (
  m1.size === m2.size &&
  (new Map([...m1, ...m2])).size === m1.size
)

console.info('Compare A & B: ', compareMap(A, B));
console.info('Compare A & C: ', compareMap(A, C));
console.info('Compare B & C: ', compareMap(B, C));

Если вы не знали: фрагменты кода имеют встроенную кнопку автоформатирования: i.stack.imgur.com/RwGHH.png

Fabian N. 27.08.2018 12:07

Спасибо за редактирование выравнивания. Тем не менее, люди должны сосредоточиться на контенте (по крайней мере, когда он двухстрочный), но да, доза выравнивания имеет значение для лучшей видимости фактического контента!

Koushik Chatterjee 27.08.2018 12:49

Вот один лайнер, обернутый функцией TypeScript.

function sameKeys(a: Map<string, string>, b: Map<string, string>): boolean {
    return a.size === b.size && [...a.keys()].every(key => b.has(key))
}

Другие вопросы по теме