المعلمات الافتراضية تجزئة متعددة المستويات عند الوصول إلى مفاتيح غير موجودة كما في H [1] [1] += 1 [مكررة

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

  •  01-10-2019
  •  | 
  •  

سؤال

أحاول إنشاء ملف Hash من Hash-es. إن قيمة التجزئة من المستوى الثاني هي عبارة عن عدد صحيح تم تقصيره إلى 0. ما أحاول القيام به هو البدء بتجزئة فارغة من الجزاز مع القيمة الافتراضية.

عندما أحاول ذلك ببسيط Hash من الأعداد الصحيحة ، يعمل بشكل جيد:

irb(main):003:0> h = Hash.new(0)
=> {}
irb(main):004:0> h[1] += 1
=> 1
irb(main):005:0> p h
{1=>1}
=> nil
irb(main):006:0> h.keys.size
=> 1
irb(main):007:0>

h الآن لديه مفتاح واحد وقيمة 1. مثالية.

ولكن عندما تكون قيم التجزئة الخاصة بي تجزئة ، لا يبدو أنها تعمل:

irb(main):007:0> h = Hash.new(Hash.new(0))
=> {}
irb(main):008:0> h[1][1] += 1
=> 1
irb(main):009:0> p h
{}
=> nil
irb(main):010:0> h.keys.size
=> 0
irb(main):011:0>

هل أفعل شيئًا خاطئًا ، أو لا يمكنني تعيين القيمة الافتراضية لتجزئة إلى Hash.new(0)?

تعديل:

بناءً على الإجابات أدناه ، تمكنت من معرفة ما كنت أفعله خطأ. في الواقع ، تمكنت من معرفة مكان تفكيري. قصة طويلة قصيرة، h[1][1] لا عش Hash.new المكالمات ، ما لم تعطي Hash.new كتلة من الكود للاتصال. قيمة التعبير h[1][1] += 1 هو 1 كما هو متوقع ، ولكن تم تهيئة تجزئة الأعمق فقط بشكل صحيح.

أنا أنشر هذا لأنه على الرغم من أن المثال أعلاه يستخدم تجزئة ثنائية الأبعاد ، فإن مشكلتي الفعلية تستخدم تجزئة ثلاثية الأبعاد:

syms[level][exchange][symbol] = count

قد يكون الحل مفيدًا للآخرين الذين يعانون من هذه المشكلة ، لذا فإليك الرمز الذي يعمل هذا بالطريقة التي أريدها:

irb(main):024:0> syms = Hash.new{|h1,k1| h1[k1] = Hash.new{|h2,k2| h2[k2] = Hash.new(0)}}
=> {}
irb(main):026:0> syms["level1"]["NYSE"]["IBM"] += 1
=> 1
irb(main):027:0> p syms
{"level1"=>{"NYSE"=>{"IBM"=>1}}}
=> nil
irb(main):028:0>
هل كانت مفيدة؟

المحلول

الطريقة الأكثر عمومية لتعيين قيمة افتراضية عند إنشاء علامة تجزئة هي استخدام وظيفة التجزئة الجديدة مع وسيطة كتلة:

h = Hash.new { |h, k| h[k] = Hash.new(0) }

المشكلة التي لديك هي أنك تقوم بتعيين الافتراضي على مؤشر كائن بدلاً من جزء من التعليمات البرمجية المراد تنفيذه. أي في كل مرة يتم فيها الوصول إلى قيمة مفقودة في التجزئة "الخارجية" ، فإنه يعيد مؤشرًا إلى مثلها بالضبط هدف. لإثبات هذا لنفسك ، جرب هذا:

>> h = Hash.new(Hash.new(0))
=> {}
>> h[1] === h[2]
=> true

وانت ايضا يستطيع في الواقع ، قم بتعيين القيمة الافتراضية لجسم التجزئة ، لكن القيام بذلك لن ينجز ما تريد. زيادة H [1] [1] سيغير في الواقع التجزئة الافتراضية نفسها ، حيث لم يتم تهيئة H [1].

أتمنى أن يساعدك هذا.

نصائح أخرى

h = Hash.new(Hash.new(0))

hash.new (0) هو الكائن الافتراضي ؛ إنه نفس الكائن لكل مفتاح غير محدد. إنه ما يعود به التجزئة عندما لا يكون المفتاح موجودًا.

h = Hash.new{|h,k| h[k]=Hash.new(0)}

The {| H ، K | H [k] = hash.new (0)} هو proc الافتراضي. يعمل عندما يكون المفتاح غائبًا ويخلق ملف الجديد التجزئة (الافتراضي إلى 0.) لكل مفتاح غير موجود.

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