10

関数の引数のリストを文字列に正規化するにはどうすればよいですか? 2 つの引数リストが実質的に同等である場合に同じ文字列に変換されるようにするにはどうすればよいですか? アルゴリズムは

  1. 参照ではなく、埋め込まれたハッシュとリストを深く比較する
  2. ハッシュキーの順序を無視
  3. 3 と "3" の違いを無視する
  4. 比較的読みやすい文字列を生成します (必須ではありませんが、デバッグ用にあると便利です)
  5. 良好なパフォーマンス (Perl よりも XS を推奨)

これはmemoization、つまり引数に基づいて関数の結果をキャッシュするために必要です。

ストローマンの例として、Memoizeはこれをデフォルトのノーマライザーとして使用しますが、これは #1 と #3 に失敗します。

$argstr = join chr(28),@_;  

しばらくの間、私の頼りになるノーマライザーは

JSON::XS->new->utf8->canonical

ただし、最近のスカラーの使用方法に基づいて、数値 3 と文字列 "3" の扱いが異なります。これにより、本質的に同等の引数リストに対して異なる文字列が生成され、メモ化の利点が減少する可能性があります。(大部分の関数は、3 になるか「3」になるかを知りませんし、気にもしません。)

楽しみのために、シリアライザーの束を調べて、どのシリアライザーが 3 と "3" を区別しているかを確認しました。

Data::Dump   : equal - [3] vs [3]
Data::Dumper : not equal - [3] vs ['3']
FreezeThaw   : equal - FrT;@1|@1|$1|3 vs FrT;@1|@1|$1|3
JSON::PP     : not equal - [3] vs ["3"]
JSON::XS     : not equal - [3] vs ["3"]
Storable     : not equal - <unprintable>
YAML         : equal - ---\n- 3\n vs ---\n- 3\n
YAML::Syck   : equal - --- \n- 3\n vs --- \n- 3\n
YAML::XS     : not equal - ---\n- 3\n vs ---\n- '3'\n

「等しい」と報告するもののうち、ハッシュキーの順序を無視する方法がわかりません。

引数リストを前もって調べて、すべての数値を文字列化することもできますが、これにはディープ コピーを作成する必要があり、#5 に違反します。

ありがとう!

4

2 に答える 2

2

ほとんどのシリアライザーは、数値と文字列化された数値が同じであるという知識がなく、この仮定が一般的なデータに対して間違っているため、3 と "3" を異なる方法で扱います。入力または出力のいずれかを自分で正規化する必要があります。

入力の場合、文字列化された数値をその値+0に置き換えるディープスキャンで十分です。正確に数値が入力されている可能性がある場所がわかっている場合は、このスキャンを大幅に短縮できます。

出力については、いくつかの単純なステート マシンまたは正規表現 (はい、出力が規則的でないことはわかっています) で、数値のみの文字列値を数値に削除するのに十分な可能性が高くなります。

于 2012-05-31T14:12:28.150 に答える
2

YAMLおよびその子孫はデフォルトでハッシュキーをソートします。$YAML::SortKeys = 2深いハッシュでソートするように設定します。

$YAML::Stringifytrue 値に設定し$YAML::XS::QuoteNumericStrings、false 値に設定すると、数値を正規化するのに役立ちます。後者の設定は、数値のように見える文字列値を「引用解除」します。


また、 を使用$Data::Dumper::Sortkeys = 1して出力順序を正規化することもできますData::Dumper。設定$Data::Dumper::Useqq = 1により、数字のように見える文字列の引用符が解除されます。

于 2012-05-31T15:23:34.363 に答える