هل هناك أي نوع من التجزئة رمز وظيفة في جافا سكريبت ؟

StackOverflow https://stackoverflow.com/questions/194846

  •  10-07-2019
  •  | 
  •  

سؤال

أساسا أنا أحاول إنشاء كائن من كائنات فريدة من نوعها،.لدي فكرة رائعة فقط باستخدام كائن جافا سكريبت مع الكائنات الأسماء الملكية.مثل ،

set[obj] = true;

يعمل هذا, إلى حد ما.يعمل كبيرة مع سلسلة من الأرقام ، ولكن مع كائنات أخرى ، يبدو أنهم جميعا أن "تجزئة" إلى نفس القيمة و الوصول إلى نفس المنشأة.هل هناك طريقة أستطيع توليد فريدة من نوعها تجزئة القيمة كائن ؟ كيف سلاسل الأرقام تفعل ذلك ، يمكن تجاوز نفس السلوك ؟

هل كانت مفيدة؟

المحلول

وجافا سكريبت ويمكن استخدام الأجسام سلاسل فقط كمفاتيح (يتم تحويل أي شيء آخر إلى سلسلة).

هل يمكن، بدلا من ذلك، والحفاظ على صفيف الذي الفهارس الكائنات في السؤال، واستخدام سلسلة مؤشره كمرجع إلى كائن. شيء من هذا القبيل:

var ObjectReference = [];
ObjectReference.push(obj);

set['ObjectReference.' + ObjectReference.indexOf(obj)] = true;

من الواضح انها مطول قليلا، ولكن هل يمكن أن يكتب بضع الأساليب التي تعامل معها والحصول على وتعيين كافة شاء أم أبى.

وتحرير:

<اقتباس فقرة>   

وتخمين الخاص بك هو الواقع - وهذا هو تعريف السلوك في جافا سكريبت - على وجه التحديد يحدث تحويل toString مما يعني أنه يمكنك ان تحدد وظيفة toString الخاصة بك على الكائن الذي سيتم استخدامه كاسم الممتلكات. - olliej

وهذا إحضار نقطة أخرى مثيرة للاهتمام، يمكنك تحديد طريقة toString على الكائنات التي تريد تجزئة، والتي يمكن أن تشكل معرف التجزئة الخاصة بهم.

نصائح أخرى

إذا كنت ترغب في وظيفة شفرة التجزئة () مثل جافا في جافا سكريبت، وهذا هو لك:

String.prototype.hashCode = function(){
    var hash = 0;
    for (var i = 0; i < this.length; i++) {
        var character = this.charCodeAt(i);
        hash = ((hash<<5)-hash)+character;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
}

وهذا هو السبيل التنفيذ في جاوة (المشغل أحادي المعامل).

وأسهل طريقة للقيام بذلك هي لإعطاء كل من الأشياء الخاصة بك الخاصة بها طريقة toString فريدة من نوعها:

(function() {
    var id = 0;

    /*global MyObject */
    MyObject = function() {
        this.objectId = '<#MyObject:' + (id++) + '>';
        this.toString= function() {
            return this.objectId;
        };
    };
})();

وكان لي نفس المشكلة وهذا حلها تماما بالنسبة لي مع الحد الأدنى من الجلبة، وكان من الأسهل كثيرا أن إعادة تنفيذ-بعض Hashtable الدهنية أسلوب جافا وإضافة equals() وhashCode() إلى فئات وجوه الخاص بك. فقط تأكد من أن كنت لا عصا أيضا سلسلة '<#MyObject: 12>. إلى تجزئة أو أنها سوف تمحو دخول لكائن الخروج مع أن معرف

والآن كل تجزئات بلادي هي البرد تماما. وأود أيضا أن مجرد نشر بلوق الدخول قبل بضعة أيام حول هذا الموضوع بالضبط .

والحل اخترت مشابها لدانيال، ولكن بدلا من استخدام المصنع الكائن وتجاوز toString، أود أن أضيف صراحة التجزئة إلى كائن عند طلب لأول مرة من خلال وظيفة getHashCode. وهناك القليل من الفوضى، ولكن أفضل لاحتياجاتي:)

Function.prototype.getHashCode = (function(id) {
    return function() {
        if (!this.hashCode) {
            this.hashCode = '<hash|#' + (id++) + '>';
        }
        return this.hashCode;
    }
}(0));

ما وصفته أنت تغطيها الوئام WeakMaps ، وهي جزء من ECMAScript 6 مواصفات (النسخة المقبلة من جافا سكريبت). وهذا هو: مجموعة حيث مفاتيح يمكن أن يكون أي شيء (بما في ذلك غير معروف) وغير قابلة للenumerable

وهذا يعني أنه من المستحيل الحصول على مرجع إلى قيمة ما لم يكن لديك إشارة مباشرة إلى مفتاح (أي كائن!) الذي يربط به. من المهم لمجموعة من الأسباب تنفيذ المحرك المتعلقة الكفاءة وجمع القمامة، لكنه أيضا أكثر من رائع لفي أنه يتيح للدلالات جديدة مثل أذونات الوصول revokable وتمرير البيانات دون تعريض مرسل البيانات.

MDN :

var wm1 = new WeakMap(),
    wm2 = new WeakMap();
var o1 = {},
    o2 = function(){},
    o3 = window;

wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // A value can be anything, including an object or a function.
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // Keys and values can be any objects. Even WeakMaps!

wm1.get(o2); // "azerty"
wm2.get(o2); // Undefined, because there is no value for o2 on wm2.
wm2.get(o3); // Undefined, because that is the set value.

wm1.has(o2); // True
wm2.has(o2); // False
wm2.has(o3); // True (even if the value itself is 'undefined').

wm1.has(o1);   // True
wm1.delete(o1);
wm1.has(o1);   // False
تتوفر

وWeakMaps في فايرفوكس الحالي، والكروم والحافة. كنت دعمها أيضا في V7 عقدة، وفي V6 مع العلم --harmony-weak-maps.

لوضعي معين ما يهمني هو المساواة بين الكائن بقدر المفاتيح والقيم البدائية تذهب. الحل الذي عملت بالنسبة لي هو تحويل الكائن إلى التمثيل JSON ويستخدم أن مثل التجزئة. هناك قيود مثل ترتيب تعريف المفتاح يحتمل أن تكون غير متناسقة. ولكن كما قلت لأنها عملت لي لأن هذه الأشياء كانت كلها تتولد في مكان واحد.

var hashtable = {};

var myObject = {a:0,b:1,c:2};

var hash = JSON.stringify(myObject);
// '{"a":0,"b":1,"c":2}'

hashtable[hash] = myObject;
// {
//   '{"a":0,"b":1,"c":2}': myObject
// }

ومواصفات جافا سكريبت تحدد الوصول الملكية مفهرسة كما يؤدون تحويل toString على اسم المؤشر. على سبيل المثال،

myObject[myProperty] = ...;

وهو نفس

myObject[myProperty.toString()] = ...;

وهذا أمر ضروري كما هو الحال في جافا سكريبت

myObject["someProperty"]

وهو نفس

myObject.someProperty

ونعم، يجعلني حزينا أيضا: - (

ولقد وضعت وحدة جافا سكريبت صغيرة منذ فترة لإنتاج hashcodes سلاسل، والكائنات، المصفوفات، وما إلى ذلك (أنا فقط ارتكب ل جيثب :))

والاستعمال:

Hashcode.value("stackoverflow")
// -2559914341
Hashcode.value({ 'site' : "stackoverflow" })
// -3579752159

في ECMAScript 6 هناك الآن Set الذي يعمل كيف تريد: <لأ href = "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set" يختلط = "noreferrer"> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

وأنها متاحة بالفعل في أحدث كروم، FF، وIE11.

والمرجعي: الشبكي: //developer.mozilla كافيه / EN-US / مستندات / الانترنت / جافا سكريبت / المرجع / Global_Objects / رمز

ويمكنك استخدام رمز ES6 لإنشاء مفتاح فريد والكائن الوصول.     كل قيمة رمز عاد من رمز () هي فريدة من نوعها. يمكن استخدام قيمة رمز كمعرف لخصائص الكائن؛ وهذا هو الغرض الوحيد نوع البيانات ل.

var obj = {};

obj[Symbol('a')] = 'a';
obj[Symbol.for('b')] = 'b';
obj['c'] = 'c';
obj.d = 'd';

إليك بلدي حل بسيط تقوم بإرجاع عدد صحيح فريدة من نوعها.

function hashcode(obj) {
    var hc = 0;
    var chars = JSON.stringify(obj).replace(/\{|\"|\}|\:|,/g, '');
    var len = chars.length;
    for (var i = 0; i < len; i++) {
        // Bump 7 to larger prime number to increase uniqueness
        hc += (chars.charCodeAt(i) * 7);
    }
    return hc;
}

وبلدي حل يقدم وظيفة ثابتة للكائن Object العالمي.

(function() {
    var lastStorageId = 0;

    this.Object.hash = function(object) {
        var hash = object.__id;

        if (!hash)
             hash = object.__id = lastStorageId++;

        return '#' + hash;
    };
}());

وأعتقد أن هذا هو أكثر ملاءمة مع كائن آخر التلاعب وظائف في جافا سكريبت.

إذا كنت تريد حقا سلوك مجموعة (أنا ذاهب من المعرفة جافا)، وبعد ذلك سوف يكون من الصعب إيجاد حل في جافا سكريبت. ومعظم المطورين يوصي مفتاح فريد لتمثيل كل كائن، ولكن هذا لا يشبه مجموعة، في أنه يمكنك الحصول على كائنين متطابقة مع كل مفتاح فريد. وAPI جافا لا عمل من التحقق من وجود قيم مكررة بمقارنة قيم رمز التجزئة، وليس مفاتيح، ونظرا لعدم وجود قيمة تمثيل رمز التجزئة من الكائنات في جافا سكريبت، يصبح من المستحيل تقريبا أن تفعل الشيء نفسه. حتى مكتبة نموذج JS يعترف هذا القصور، عندما يقول:

<اقتباس فقرة>   

و"تجزئة يمكن اعتبار ل   مجموعة النقابي، مفاتيح فريدة من نوعها ملزمة   إلى القيم (التي ليست بالضرورة   فريد) ... "

http://www.prototypejs.org/api/hash

وبالإضافة إلى الإجابة eyelidlessness، وهنا هي وظيفة يقوم بإرجاع استنساخه، ID فريدة من نوعها لأية وجوه:

var uniqueIdList = [];
function getConstantUniqueIdFor(element) {
    // HACK, using a list results in O(n), but how do we hash e.g. a DOM node?
    if (uniqueIdList.indexOf(element) < 0) {
        uniqueIdList.push(element);
    }
    return uniqueIdList.indexOf(element);
}

وكما ترون فإنه يستخدم القائمة لنظرة المتابعة التي هي غير فعالة للغاية، ولكن هذا هو أفضل ما يمكن أن تجد في الوقت الراهن.

إذا كنت تريد استخدام الكائنات كمفاتيح تحتاج إلى الكتابة أسلوب toString بهم، وبعض التي سبق ذكرها هنا. وظائف التجزئة التي كانت تستخدم كلها الجميلة، لكنها تعمل فقط لنفس الأشياء لا للكائنات متساوية.

ولقد كتب مكتبة صغيرة أن يخلق التجزئة من الأشياء، والتي يمكنك استخدامها بسهولة لهذا الغرض. يمكن الكائنات حتى يكون ترتيب مختلف، فإن التجزئة تكون هي نفسها. داخليا يمكنك استخدام أنواع مختلفة للتجزئة الخاص بك (djb2، MD5، SHA1، SHA256، SHA512، ripemd160).

وهنا مثال صغير من الوثائق:

var hash = require('es-hash');

// Save data in an object with an object as a key
Object.prototype.toString = function () {
    return '[object Object #'+hash(this)+']';
}

var foo = {};

foo[{bar: 'foo'}] = 'foo';

/*
 * Output:
 *  foo
 *  undefined
 */
console.log(foo[{bar: 'foo'}]);
console.log(foo[{}]);

ويمكن استخدام حزمة إما في المتصفح وفي عقدة-شبيبة.

ومستودع: https://bitbucket.org/tehrengruber/es-js-hash

إذا كنت تريد أن يكون لها قيم فريدة في بحث كائن يمكنك أن تفعل شيئا مثل هذا:

إنشاء بحث وجوه

var lookup = {};

إعداد hashcode وظيفة

function getHashCode(obj) {
    var hashCode = '';
    if (typeof obj !== 'object')
        return hashCode + obj;
    for (var prop in obj) // No hasOwnProperty needed
        hashCode += prop + getHashCode(obj[prop]); // Add key + value to the result string
    return hashCode;
}

وجوه

var key = getHashCode({ 1: 3, 3: 7 });
// key = '1337'
lookup[key] = true;

مجموعة

var key = getHashCode([1, 3, 3, 7]);
// key = '01132337'
lookup[key] = true;

أنواع أخرى

var key = getHashCode('StackOverflow');
// key = 'StackOverflow'
lookup[key] = true;

النتيجة النهائية

{ 1337: true, 01132337: true, StackOverflow: true }

ملاحظة أن getHashCode لا ترجع أي قيمة عند الكائن أو صفيف فارغ

getHashCode([{},{},{}]);
// '012'
getHashCode([[],[],[]]);
// '012'

هذا هو مماثل @ijmacd الحل الوحيد getHashCode لا يملك JSON التبعية.

سأحاول أن نذهب أعمق قليلا من إجابات أخرى.

حتى لو شبيبة كان أفضل تجزئة الدعم لن سحرية تجزئة كل شيء تماما في كثير من الحالات سيكون لديك لتحديد الخاصة بك وظيفة تجزئة.على سبيل المثال جافا جيد تجزئة الدعم ، ولكن لا يزال لديك للتفكير والعمل.

مشكلة واحدة مع مصطلح التجزئة/hashcode ...هناك تجزئة التشفير وعدم تجزئة التشفير.مشكلة أخرى ، يجب أن نفهم لماذا تجزئة مفيد و كيف يعمل.

عندما نتحدث عن تجزئة في جافا سكريبت أو جافا معظم الوقت نحن نتحدث عن عدم تجزئة التشفير عادة عن تجزئة على hashmap/hashtable (إلا إذا كنا نعمل على المصادقة أو كلمات السر التي يمكن أن تقوم به من جانب الملقم باستخدام NodeJS ...).

ذلك يعتمد على البيانات التي لديك وما تريد تحقيقه.

البيانات الخاصة بك لديه بعض الطبيعية "بسيطة" التفرد:

  • تجزئة عدد صحيح هو ...عدد صحيح ، كما أنها فريدة من نوعها ، أنت محظوظ !
  • تجزئة سلسلة ...ذلك يعتمد على السلسلة ، إذا كانت السلسلة يمثل معرف فريد ، قد تنظر فيه بوصفه تجزئة (حتى لا تجزئة الحاجة).
  • أي شيء غير مباشرة إلى حد كبير فريد من نوعه عدد صحيح هو أبسط الحالات
  • هذا الصدد:hashcode متساوية إذا الأجسام متساوية

البيانات الخاصة بك لديه بعض الطبيعية "المركب" التفرد:

  • على سبيل المثال مع شخص كائن يمكنك حساب تجزئة باستخدام firstname, lastname, تاريخ الميلاد, ...انظر كيف جافا لا: وظيفة جيدة التجزئة سلاسل, أو استخدام معرف معلومات رخيصة فريدة من نوعها بما فيه الكفاية بالنسبة usecase

لديك أي فكرة عما سوف تكون البيانات الخاصة بك:

  • حظا سعيدا ...هل يمكن إجراء تسلسل إلى سلسلة تجزئة عليه جافا النمط ، ولكن قد تكون مكلفة إذا كانت السلسلة كبيرة ولن تجنب التصادم وكذلك القول تجزئة عدد صحيح (النفس).

لا يوجد سحرية فعالة تجزئة تقنية مجهولة البيانات في بعض الحالات فإنه من السهل جدا في حالات أخرى قد تحتاج إلى التفكير مرتين.لذلك حتى لو كان جافا سكريبت/ECMAScript يضيف المزيد من الدعم ليس هناك سحر في اللغة حل لهذه المشكلة.

في الممارسة العملية تحتاج إلى أمرين:يكفي تفرد ما يكفي من السرعة

بالإضافة إلى أنه أمر رائع أن يكون:"hashcode متساوية إذا الأجسام متساوية"

أنا جنبا إلى جنب إجابات من eyelidlessness و KimKha.

وفيما يلي angularjs خدمة وتدعم أرقام, سلاسل, والكائنات.

exports.Hash = () => {
  let hashFunc;
  function stringHash(string, noType) {
    let hashString = string;
    if (!noType) {
      hashString = `string${string}`;
    }
    var hash = 0;
    for (var i = 0; i < hashString.length; i++) {
        var character = hashString.charCodeAt(i);
        hash = ((hash<<5)-hash)+character;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
  }

  function objectHash(obj, exclude) {
    if (exclude.indexOf(obj) > -1) {
      return undefined;
    }
    let hash = '';
    const keys = Object.keys(obj).sort();
    for (let index = 0; index < keys.length; index += 1) {
      const key = keys[index];
      const keyHash = hashFunc(key);
      const attrHash = hashFunc(obj[key], exclude);
      exclude.push(obj[key]);
      hash += stringHash(`object${keyHash}${attrHash}`, true);
    }
    return stringHash(hash, true);
  }

  function Hash(unkType, exclude) {
    let ex = exclude;
    if (ex === undefined) {
      ex = [];
    }
    if (!isNaN(unkType) && typeof unkType !== 'string') {
      return unkType;
    }
    switch (typeof unkType) {
      case 'object':
        return objectHash(unkType, ex);
      default:
        return stringHash(String(unkType));
    }
  }

  hashFunc = Hash;

  return Hash;
};

مثال على الاستخدام:

Hash('hello world'), Hash('hello world') == Hash('hello world')
Hash({hello: 'hello world'}), Hash({hello: 'hello world'}) == Hash({hello: 'hello world'})
Hash({hello: 'hello world', goodbye: 'adios amigos'}), Hash({hello: 'hello world', goodbye: 'adios amigos'}) == Hash({goodbye: 'adios amigos', hello: 'hello world'})
Hash(['hello world']), Hash(['hello world']) == Hash(['hello world'])
Hash(1), Hash(1) == Hash(1)
Hash('1'), Hash('1') == Hash('1')

الإخراج

432700947 true
-411117486 true
1725787021 true
-1585332251 true
1 true
-1881759168 true

تفسير

كما ترون قلب خدمة دالة البعثرة التي أنشأتها KimKha.واضاف لقد أنواع السلاسل بحيث sturucture من وجوه أيضا تأثير النهائي تجزئة القيمة.مفاتيح يتم تجزئته إلى منع مجموعة|وجوه التصادم.

eyelidlessness وجوه المقارنة يستخدم لمنع infinit العودية الذاتي الرجوع الكائنات.

الاستخدام

أنا خلقت هذه الخدمة بحيث يمكن أن يكون خطأ الخدمة التي يتم الوصول إليها مع الكائنات.حيث أن خدمة واحدة يمكنك تسجيل خطأ معين موضوع آخر يمكن تحديد ما إذا كان تم العثور على أخطاء.

أي

JsonValidation.js

ErrorSvc({id: 1, json: '{attr: "not-valid"}'}, 'Invalid Json Syntax - key not double quoted');

UserOfData.js

ErrorSvc({id: 1, json: '{attr: "not-valid"}'});

وهذا من شأنه العودة:

['Invalid Json Syntax - key not double quoted']

في حين

ErrorSvc({id: 1, json: '{"attr": "not-valid"}'});

هذا سيعود

[]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top