Создать уникальный ключ/хеш на основе объекта

Скажем, у меня есть следующие объекты JavaScript:

const obj1 = {
 key1: 'str1',
 key2: 'str2'
}

const obj2 = {
 key2: 'str2',
 key1: 'str1'
}

const obj3 = {
 key1: 'something else',
 key2: 'str2'
}

const obj4 = {
 differentKey: 'str1',
 key2: 'str2'
}

Я хотел бы создать уникальный ключ на основе данного объекта. Это сделано для того, чтобы я мог правильно кэшировать некоторые данные, относящиеся к каждому объекту в структуре Map. В этом сценарии obj1 и obj2 должны иметь один и тот же ключ, поскольку единственная разница — это порядок свойств. obj3 и obj4 должны иметь разные ключи. Я пробовал использовать JSON.stringify(), но это дает разные результаты для obj1 и obj2 из-за порядка. Есть ли способ обойти это?

Я приму ответ, который обрабатывает только примитивные типы, но и ответ, который обрабатывает не примитивные типы, также будет принят, и это было бы здорово!

Пожалуйста, поделитесь своей попыткой, используя JSON.stringify()

mykaf 05.08.2024 16:49

Если JSON.stringify для вас приемлемо, это звучит так, будто длина «ключа» не вызывает беспокойства, в то время как вероятность столкновения даже в одну триллионную долю? И какие это могут быть свойства? Например, создание ключа для свойств символа кажется настоящей проблемой (невозможной?).

ASDFGerte 05.08.2024 16:53

@mykaf Это кажется ненужным; его легко воспроизвести, вызвав JSON.stringify для любых двух объектов с ключами в разном порядке.

Unmitigated 05.08.2024 16:54

@MarkBaijens Это похоже, но не отвечает, как сгенерировать хеш для объекта, игнорируя порядок ключей. Задавший не должен отвечать за то, чтобы отличать свой вопрос от любого другого аналогичного вопроса в Stack Overflow.

Unmitigated 05.08.2024 16:59

сложность ответа зависит от сложности реальных объектов, с которыми вам придется иметь дело. Тривиальные примеры в вопросе легко обрабатываются.

Jaromanda X 05.08.2024 17:01

@Unmitigated Насколько я понимаю, ОП пытается решить проблему сравнения объектов в Javascript. Он предполагает, что хеш может быть одним из способов решения этой проблемы. Однако я не думаю, что хэш будет полезен для понимания того, как работают объекты. Поэтому дубликат, на мой взгляд, очень подходит.

Mark Baijens 05.08.2024 17:02

@MarkBaijens В вопросе упоминаются только данные кэширования, связанные с объектами, например. в структуре хэш-карты. Если вы не предложите сравнить ключ с любым другим ключом на карте, это не даст полного ответа на вопрос.

Unmitigated 05.08.2024 17:09

Для преобразования любого произвольного объекта в хэш потребуется специальный код для работы с определенными структурами данных. Какие свойства должны способствовать хешу? Чего не должно быть? Какие части графа объекта важны? Как сравнивать функции? Как обращаться с циклами? На этот вопрос нет однозначного ответа, кроме как сказать, что простейший возможный способ различения «ключевых» объектов, вероятно, является хорошей отправной точкой.

Pointy 05.08.2024 17:54

Привет всем, спасибо за ваши комментарии! Я хочу уточнить, что я приму ответ, который обрабатывает только примитивные типы в плоском объекте. Однако я не хотел никого отговаривать от публикации решения, которое обрабатывает более сложные типы, такие как функции или вложенные структуры.

Matt 05.08.2024 18:57

Чтобы ответить @Unmitigated, да, мне нужен ключ, который я могу использовать в экземпляре Map.

Matt 05.08.2024 18:58

@Matt Это разъяснение следует включить в сам вопрос.

Unmitigated 05.08.2024 19:47

@MarkBaijens «Однако я не думаю, что хеш будет полезен для понимания того, как работают объекты. Поэтому, на мой взгляд, дубликат очень подходит». вы просто пытаетесь ответить на другой вопрос, отличный от заданного. Если вы не знаете, попросите разъяснений. И считайте закрытие неясным, если на него действительно нельзя ответить. Однако не закрывайте вопрос об А просто как о Б. Если будущий посетитель будет искать, как хешировать объект (А), ему не будет предложено узнать, как сравнивать объекты (Б). Принимая решение в пользу ОП, вы также утверждаете, что все запросы об А на самом деле касаются Б.

VLAZ 06.08.2024 12:46
Поведение ключевого слова "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
12
74
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Здесь более развернутый ответ на аналогичный вопрос (написанный не мной) https://stackoverflow.com/a/1069840/20932276

Вы не можете надежно «привести» объект к массиву; вы, конечно, можете реализовать что-то, что преобразует определенные типы объектов, важных для конкретного приложения, но в целом эта концепция не имеет смысла.

Pointy 05.08.2024 17:52
Ответ принят как подходящий

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

Не стесняйтесь настраивать проверку типа объекта (isObject) в соответствии с вашими потребностями.

Обновлено: Как упоминал VLAZ, JSON.stringify может исключать определенные типы значений. А именно функция, символ или неопределенное. Я обновил пример для обработки undefined, и при необходимости вы можете расширить функцию replacer для обработки функций и символов.

function sort(object) {
  const sortedEntries = Object.entries(object).sort((a, b) =>
    a[0].localeCompare(b[0])
  );

  const withSortedValues = sortedEntries.map(([key, value]) => {
    const isObject = typeof value === 'object' && value !== null
    const newVal = isObject ? sort(value) : value;
    return [key, newVal];
  });

  return Object.fromEntries(withSortedValues);
}

// Edit: Replacer function to keep undefined values
// and replace them with a placeholder. Feel free to
// change the placeholder to your needs (another string or null)
function replacer(k,v) {
  return v === undefined ? "[undefined]" : v;
}

function compare(obj1, obj2) {
  return JSON.stringify(sort(obj1), replacer) === JSON.stringify(sort(obj2), replacer);
}

const obj1 = {
  a: 1,
  b: { c: 1, d: 2 },
};
const obj2 = {
  b: { d: 2, c: 1 },
  a: 1,
};
const obj3 = {
  b: { d: 4, c: 3 },
  a: 1,
};
const obj4 = {
  a: 1,
  b: { c: 1, d: 2},
  c: undefined
}

console.info('1 == 2', compare(obj1, obj2)); // true
console.info('1 == 3', compare(obj1, obj3)); // false
// Edit: Handling a normally excluded value tyoe, i.e. undefined
console.info('1 == 4', compare(obj1, obj4)); // false
JSON.stringify не является надежным решением. При сериализации будут пропущены некоторые ключи вместе с их ключом. Рассмотрим compare( { a: 1, b: 2 }, { a: 1, b: 2, c: undefined }); (демо)
VLAZ 06.08.2024 13:14

Это хороший момент, и его важно иметь в виду. Является ли это препятствием или нет, в конечном итоге будет зависеть от варианта использования OP и способа создания объекта.

Brother58697 06.08.2024 14:32

@VLAZ Я обновил ответ, чтобы обрабатывать значения undefined. JSON.stringify также исключим функции и символы, но оставлю это подразумеваемым. до ОП и их потребностей.

Brother58697 06.08.2024 14:48

Это работает. Я не рассматривал возможность просто поставить JSON.stringify() и рассортировать объект. Спасибо!

Matt 06.08.2024 20:42

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