التابع Enumerable.slice_before
في روبي
يقطِّع التابع slice_before
عناصر الكائن القابل للتعداد إلى أجزاء تحدَّد بدايتها عبر نمطٍ محدِّدٍ أو كتلةٍ معطاةٍ ثم يعيد مُعدِّد لكل جزء من الأجزاء الناتجة.
البنية العامة
slice_before(pattern) → an_enumerator
slice_before { |elt| bool } → an_enumerator
إن كان النمط مطابقًا للعنصر (أي يعيد pattern === elt
القيمة true
) أو أعادت الكتلة القيمة true
للعنصر المُمرَّر إليها، فسيُعدُّ العنصر بدايةً لجزء. يُستدعَى المعامل ===
والكتلة block
من أول عنصر وحتى آخر عنصر من عناصر الكائن القابل للتعداد المعطى. يجري دومًا تجاهل النتيجة المعادة لأول عنصر.
يُنتِج المُعدِّد المعاد العناصر المُجزَّأة كمصفوفة. لذلك، يمكن استدعاء التابع each
بالشكل التالي:
enum.slice_before(pattern).each { |ary| ... }
enum.slice_before { |elt| bool }.each { |ary| ... }
يمكن أيضًا استعمال توابع الصنف Enumerator
والوحدة Enumerable
مثل التابع map
وغيره.
المعاملات
pattern
النمط المراد مطابقته للعناصر لتحديد نهايات الأجزاء المراد تقطيع عناصر الكائن المعطى إليها.
القيمة المعادة
يعاد مُعدِّد لكل جزء من الأجزاء المُقطَّعة.
أمثلة
مثال على التكرار عبر مدخلات ChangeLog باستعمال التابع slice_before
:
open("ChangeLog") { |f|
f.slice_before(/\A\S/).each { |e| pp e }
}
# same as above. block is used instead of pattern argument.
open("ChangeLog") { |f|
f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
}
يُنتِج "svn proplist -R" مخرجات متعددة الأسطر لكل ملف. يمكن تقطيعهم بالشكل التالي:
IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
f.lines.slice_before(/\AProp/).each { |lines| p lines }
}
#=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"]
# ["Properties on 'goruby.c':\n", " svn:eol-style\n"]
# ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"]
# ["Properties on 'regparse.c':\n", " svn:eol-style\n"]
# ...
إن احتاجت الكتلة الحفاظ على عناصر متعددة، فيمكن آنذاك استعمال متغيرات محلية. على سبيل المثال، يمكن أن تُجمَّع ثلاثة أعداد متزايدة ومتتالية أو أكثر في أجزاء بالشكل التالي (اطلع على توثيق التابع chunk_while
، إذ توفر طريقة أفضل لأداء المهمة نفسها):
a = [0, 2, 3, 4, 6, 7, 9]
prev = a[0]
p a.slice_before { |e|
prev, prev2 = e, prev
prev2 + 1 != e
}.map { |es|
es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
}.join(",")
#=> "0,2-4,6,7,9"
على أي حال، يجب استعمال متغيرات محلية بحذر إن كان المُعدِّد الناتج يكرَّر (يُعدَّد [enumerate]) مرتين أو أكثر. يجب أن تُهيَّأ المتغيرات المحلية لكل عملية تكرار (تعداد [enumeration]). يمكن استعمال التابع Enumerator.new
لأداء ذلك.
# التفاف الكلمة. هذا يفترض أن المحارف لها العرض نفسه
def wordwrap(words, maxwidth)
Enumerator.new {|y|
# Enumerator.new في cols جرى تهيئة
cols = 0
words.slice_before { |w|
cols += 1 if cols != 0
cols += w.length
if maxwidth < cols
cols = w.length
true
else
false
end
}.each {|ws| y.yield ws }
}
end
text = (1..20).to_a.join(" ")
enum = wordwrap(text.split(/\s+/), 10)
puts "-"*10
enum.each { |ws| puts ws.join(" ") } # أول تكرار
puts "-"*10
enum.each { |ws| puts ws.join(" ") } # ولد التكرار الثاني نفس النتيجة التي ولدها الأول
puts "-"*10
#=> ----------
# 1 2 3 4 5
# 6 7 8 9 10
# 11 12 13
# 14 15 16
# 17 18 19
# 20
# ----------
# 1 2 3 4 5
# 6 7 8 9 10
# 11 12 13
# 14 15 16
# 17 18 19
# 20
# ----------
يحوي mbox سلسلة من البريد الإلكتروني الذي يبدأ بالسطر Unix From؛ لذلك، يكن استخراج كل بريد عبر تقطيعه إلى أجزاء باستعمال slice_before تسبق السطر Unix From:
# mbox تحليل
open("mbox") { |f|
f.slice_before { |line|
line.start_with? "From "
}.each { |mail|
unix_from = mail.shift
i = mail.index("\n")
header = mail[0...i]
body = mail[(i+1)..-1]
body.pop if body.last == "\n"
fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
p unix_from
pp fields
pp body
}
}
# Unix From استخراج كل بريد عبر تقطيعه إلى أجزاء تسبق السطر
open("mbox") { |f|
emp = true
f.slice_before { |line|
prevemp = emp
emp = line == "\n"
prevemp && line.start_with?("From ")
}.each { |mail|
mail.pop if mail.last == "\n"
pp mail
}
}
انظر أيضًا
- التابع
group_by
: يجمِّع عناصر الكائن القابل للتعداد الذي استدعي معه في مجموعات بحسب النتيجة المقابلة لكل عنصر التي تعيدها الكتلة المعطاة بعد تمريره إليها.
- التابع
slice_after
: يقطِّع عناصر الكائن القابل للتعداد إلى أجزاء تحدَّد نهايتها عبر نمطٍ محدِّدٍ أو كتلةٍ معطاةٍ ثم يعيد مُعدِّد لكل جزء من الأجزاء الناتجة. - التابع
slice_when
: يقطِّع عناصر الكائن القابل للتعداد إلى أجزاء تحدَّد بدايتها عبر كتلةٍ معطاةٍ ثم يعيد مُعدِّد لكل جزء من الأجزاء الناتجة.