Как мне сравнить упакованные значения в Perl?

Я хочу использовать функцию Perl pack() для кодирования некоторых данных. Затем я хочу сравнить свою упакованную структуру с другой упакованной структурой. Я хочу, чтобы это сравнение было по байтовым значениям этой упакованной структуры.

Согласно документации, cmp использует текущую локаль для определения способа сравнения строк. Но я не хочу, чтобы к сравнению применялся какой-либо интеллект. Я хочу все, что ближе всего к memcmp(). Очевидно, я не могу использовать <=> для сравнения упакованных объектов, поскольку они не являются числами.

Как лучше всего сравнивать упакованные строки в Perl?

Примечание: я читал эту статью об эффективной сортировке в Perl, в которой отмечается, что простая Функция sort использует алгоритм, подобный memcmp, для сравнения структур. Мне интересно, как добиться такого сравнения без использования сортировки.


person PP.    schedule 20.07.2010    source источник
comment
sort действительно отличное место для начала. Попытка создать собственную сортировку-замену, вероятно, не сработает так хорошо, как хотелось бы, поскольку сортировка в Perl годами доводилась до совершенства. Ссылка на эффективную сортировку, которую вы дали, на самом деле включает инструкции о том, как использовать упакованные структуры данных для ускорения сортировки, что довольно умно, но сортировка должна занять много времени, прежде чем я посвятю себя ее поддержке.   -  person sarnold    schedule 20.07.2010
comment
Вы хотите сравнение (т. е. меньше, больше или равно) или проверку на равенство «да» или «нет»?   -  person Greg Bacon    schedule 20.07.2010
comment
@gbacon: я хочу что-то, что я могу заказать, так что меньше, больше, равно.   -  person PP.    schedule 20.07.2010
comment
perldoc.perl.org/perllocale.html#The-use-locale- pragma — говорит, что по умолчанию локаль игнорируется. Где вы прочитали, что Perl использует текущую локаль? В документах для cmp также говорится, что языковой стандарт используется «только в том случае, если действует языковой стандарт». Если действует «использовать локаль», используйте «без локали», как предлагается ниже.   -  person runrig    schedule 20.07.2010
comment
@runrig спасибо за исправление опечатки.   -  person PP.    schedule 21.07.2010


Ответы (3)


Отключите учет локали для блока и используйте cmp как обычно:

sub mycmp {
  no locale;
  $_[0] cmp $_[1];
}

Документация perlop содержит

lt, le, ge, gt и cmp используют порядок сопоставления (сортировки), указанный в текущей локали, если действует use locale. См. perllocale.

а затем в perllocale

Поведение по умолчанию восстанавливается с помощью прагмы no locale или по достижении конца блока, содержащего use locale.

Например, бег

my($one,$two) = map pack("N", $_) => 1, 2;
say mycmp($one, $two);
say mycmp($two, $one);

выходы

-1
1
person Greg Bacon    schedule 20.07.2010
comment
Не применяется ли локаль только в закрытии? Если есть локаль, которая применяется за пределами замыкания, будет ли она по-прежнему применяться к любому коду ниже замыкания? - person PP.; 21.07.2010
comment
@PP Да, прагма locale лексическая: она действует только внутри окружающего блока. - person Greg Bacon; 21.07.2010

Расширить, затем сжать. Сравните, например, шестнадцатеричное представление ваших структур, в котором используются только символы ASCII и не может столкнуться с проблемой локали, которую вы упомянули.

unpack('H*', $first) cmp unpack('H*', $second)
person daxim    schedule 20.07.2010

Здесь мысли вслух — помогут ли побитовые операторы? Подобно тому, как выполнение xor для двух идентичных строк даст битовую строку, в которой все установлено на 0.

http://perldoc.perl.org/perlop.html#Bitwise-String-Operators

person deepakg    schedule 20.07.2010
comment
xor был бы отличным тестом на равенство, независимым от локали, на самом деле - хорошая идея - не был бы полезен для меньшего/большего, чем однако. - person PP.; 20.07.2010