Как я могу создать повторяемую подпись структуры данных?

У меня есть ситуация, когда я хочу создать подпись структуры данных:

my $signature = ds_to_sig(
  { foo   => 'bar',
    baz   => 'bundy',
    boing => undef,
    number => 1_234_567,
  }
);

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

Есть ли устоявшийся способ сделать это?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
787
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Думаю, вы ищете слово "хеширование".

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

Я думаю, что вы ищете хеш-функцию. Я бы порекомендовал такой подход:

use Storable;
$Storable::canonical = 1;
sub ds_to_sig {
    my $structure = shift;
    return hash(freeze $structure);
}

Хеш-функцией может быть любая хеш-функция, например функция md5 из Дайджест :: MD5.

Хе-хе. два практически идентичных ответа менее чем за 2 минуты.

Rik 20.10.2008 18:07

Сделайте это 3 за 3 минуты! Думаю, это может означать только то, что мы все сделали правильно ;-)

Leon Timmermans 20.10.2008 18:09

Ключ там $ Storable :: canonical. Без этого Storable не гарантирует порядок элементов.

brian d foy 20.10.2008 18:36

Вероятно, вам следует использовать nfreeze для согласованности между платформами

EvdB 20.10.2008 18:54

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

структуры данных и объекты в Perl 5 в значительной степени взаимозаменяемы - объекты на самом деле являются просто благословенными ссылками на данные. В любом случае - я хочу получить подпись содержимого данных

EvdB 20.10.2008 18:21

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

Ovid 21.10.2008 19:20

Используйте Хранимый :: nstore, чтобы превратить его в двоичное представление, а затем вычислить контрольную сумму (например, с помощью модуля Digest).

Оба модуля являются базовыми модулями.

Я только что отредактировал свой код, чтобы сделать именно это. Мы с тобой снова на одном пути!

Leon Timmermans 20.10.2008 18:15
Ответ принят как подходящий

Лучший способ сделать это - использовать систему сериализации с глубокой структурой, например Хранимый. Две структуры с одинаковыми данными будут производить один и тот же большой двоичный объект вывода Storable, поэтому их можно сравнивать.

#!/usr/bin/perl

use strict;
use warnings;

use Storable ('freeze');

$Storable::canonical = 1;

my $one = { foo => 42, bar => [ 1, 2, 3 ] };
my $two = { foo => 42, bar => [ 1, 2, 3 ] };

my $one_s = freeze $one;
my $two_s = freeze $two;

print "match\n" if $one_s eq $two_s;

... И чтобы доказать обратное:

$one = [ 4, 5, 6 ];
$one_s = freeze $one;

print "no match" if $one_s ne $two_s;

Вам нужно установить $ Storable :: canonical в истинное значение. Это может не иметь значения для маленьких примеров, но важно для гораздо более крупных.

brian d foy 20.10.2008 18:37
Digest::MD5->new->add(
  Data::Dumper->new([$structure])
   ->Purity(0)
   ->Terse(1)
   ->Indent(0)
   ->Useqq(1)
   ->Sortkeys(1)
   ->Dump()
)->b64digest();

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