عودة القيم الضمنية في روبي
-
21-08-2019 - |
سؤال
وأنا جديدة نوعا ما لروبي وعلى الرغم من أن أجد لها أن تكون لغة بديهية جدا أواجه بعض صعوبة في فهم كيف تتصرف ضمني القيم العودة.
وأنا أعمل على برنامج صغير على البقرى السجلات القط وإنشاء ملفات 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
وشخصيا أجد طريقة مع عودة صريحة أكثر قابلية للقراءة (في هذه الحالة)