1

この質問のタイトルが最適かどうかはわかりませんが、この説明が私がやろうとしていることを明確にするのに役立つことを願っています. 今は午前 4 時です。ご容赦ください。ご迷惑をおかけいたします。

基本的に私がやりたいことは、ユーザーが選択した要素がサイトのページに再び表示されるかどうかを識別することです。これが使用されるのは、ユーザーがどの通知を非表示にしたかについて、サーバー側で巨大なデータベースを維持する必要なく、「二度と表示しない」通知を実装し、動的に生成された通知を作成できるようにすることです。

すべての通知に手動で一意の識別子を付与すると、動的な通知が不可能になるため、動的なソリューションが必要です。

私が考えているのは、通知のハッシュを生成することです。単純なものを使用して、通知のテキストを整理された小さなハッシュに変換し、localStorage多数の通知が使用された場合に大量のメモリを消費することなく効率的に格納できます (または、それらの通知に大量のテキストが含まれている場合)。

明らかに、MD5 や SHA-1 などは当座の候補です。これらは広く使用されており、JavaScript にはこれらの関数がネイティブではないという事実を補う多くの実装例があります。

しかし、それらは私にはやり過ぎのように思えます。私が見たすべての実装では、仕事を成し遂げるために少なくとも 12 個のヘルパー関数が定義されており、理解できないコードが使用されるのは好きではありません。その上、暗号強度は必要ありません。迅速で単純なハッシュが必要なだけです。

私は次のことを思いつきました:

function hash(str) {
    var l = str.length, i, out = 0;
    for( i=0; i<l; i++) out = (out<<1)^str.charCodeAt(i);
    return out;
}

いくつかの値でいくつかのテストを行った後、これはかなり良いハッシュを生成するようです。明らかに一貫しています。同じ入力から同じ出力が生成されます。

私が本当に知りたいのはこれです:これは使用可能なハッシュ関数ですか? つまり、このハッシュ関数を使用すると、衝突のリスクが高くなりますか?


<<回転せず、単にシフトしてオーバーフローを破棄することが指摘された後、関数は次のようになりました。

function hash(str) {
    var l = str.length, i, out = 0;
    for( i=0; i<l; i++) out = ((out<<1)|(out&0x80000000?1:0))^str.charCodeAt(i);
    return out;
}

これは基本的にビットローテーションを実装します。そのための組み込み演算子があるとは思わないからです。

4

1 に答える 1

1

いくつかのサンプルをテストしましたが、32 文字を超える文字列で末尾が同じでも同じ結果が得られるため、あまり良くないようです。

console.log(hash('Hello world. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'));
console.log(hash('Something entirely different. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'));

私にとって、これ721528210はどちらの場合にも当てはまります。

これは、バイトを << でシフトして破壊し続けると同時に、XOR ^ がペアワイズであるためだと思います。どの文字も現在の 32 バイトを変更しますが、それらはすべて 32 文字後に破棄されます。

于 2012-05-25T08:58:49.243 に答える