سؤال

وأنا جديدة نوعا ما لروبي وعلى الرغم من أن أجد لها أن تكون لغة بديهية جدا أواجه بعض صعوبة في فهم كيف تتصرف ضمني القيم العودة.

وأنا أعمل على برنامج صغير على البقرى السجلات القط وإنشاء ملفات CSV محدد الأنابيب من البيانات ذات الصلة. هنا مثال مبسط أنني أستخدم لتوليد خطوط من إدخال السجل.

class LineMatcher
  class << self
    def match(line, regex)
      output = ""
      line.scan(regex).each do |matched|
        output << matched.join("|") << "\n"
      end
      return output
    end        
  end
end


puts LineMatcher.match("00:00:13,207 06/18 INFO  stateLogger - TerminationRequest[accountId=AccountId@66679198[accountNumber=0951714636005,srNumber=20]",
                       /^(\d{2}:\d{2}:\d{2},\d{3}).*?(\d{2}\/\d{2}).*?\[accountNumber=(\d*?),srNumber=(\d*?)\]/)

وعند تشغيل هذا الرمز أعود التالية، وهو ما يتوقع عند عودته صراحة قيمة الناتج.

00:00:13,207|06/18|0951714636005|20

ولكن، إذا قمت بتغيير LineMatcher لما يلي ولا يعودون صراحة الإخراج:

    class LineMatcher
      class << self
        def match(line, regex)
          output = ""
          line.scan(regex).each do |matched|
            output << matched.join("|") << "\n"
          end
        end        
      end
    end

وثم أحصل على النتيجة التالية:

00:00:13,207
06/18
0951714636005
20

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

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

المحلول

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

و#each إرجاع جمع لك كرر جرا. قال ذلك، فإن البرمجية التالية بإرجاع قيمة line.scan (التعبير العادي).

line.scan(regex).each do |matched|
  output << matched.join("|") << "\n"
end

إذا كنت ترغب في إرجاع نتيجة تنفيذ، يمكنك استخدام map، الذي يعمل each لكن إرجاع جمع تعديلها.

class LineMatcher
  class << self
    def match(line, regex)
      line.scan(regex).map do |matched|
        matched.join("|")
      end.join("\n") # remember the final join
    end        
  end
end

وهناك العديد من الطرق المفيدة التي يمكن استخدامها تبعا لحالة محددة جدا بك. في هذا واحد قد ترغب في استخدام inject إلا إذا كان عدد من النتائج التي تم إرجاعها من قبل scan مرتفع (العمل على المصفوفات ثم دمجها هو أكثر فعالية من العمل على سلسلة واحدة).

class LineMatcher
  class << self
    def match(line, regex)
      line.scan(regex).inject("") do |output, matched|
        output << matched.join("|") << "\n"
      end
    end        
  end
end

نصائح أخرى

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

في المثال الخاص بك، المقتطف الأول إرجاع output السلسلة. ومع ذلك المقتطف الثاني إرجاع القيمة التي تم إرجاعها بواسطة الأسلوب each (والذي هو الآن stmt الماضي)، والتي تبين أن مجموعة من المباريات.

irb(main):014:0> "StackOverflow Meta".scan(/[aeiou]\w/).each do |match|
irb(main):015:1* s << match
irb(main):016:1> end
=> ["ac", "er", "ow", "et"]

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

irb(main):003:0> one_to_three = (1..3).to_a
=> [1, 2, 3]
irb(main):004:0> puts one_to_three
1
2
3
=> nil

وشخصيا أجد طريقة مع عودة صريحة أكثر قابلية للقراءة (في هذه الحالة)

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