Символите (
и )
се използват за логическо групиране на части от шаблона с цел:
day
или dance
: /\bda(y|nce)\b/
Текстът, който match-ва частта на шаблона, оградена в скоби, може да се достъпва:
\1
за първата група, \2
за втората и т.н.
MatchData
-обекта
$1
, $2
...
(?<name>)
или така: (?'name')
, където name
е името на групата
(?<date>\d{4}-\d{2}-\d{2})
/(?<date>\d{4}-\d{2}-\d{2})/.match 'Today is 2011-11-08, Tuesday.' # #<MatchData "2011-11-08" date:"2011-11-08">
\1
, \2
и прочее, ако групите ви не са именовани
\11
се обръща към 11-тата група
\1
, последван от символа 1
"?
\k<group_identifier>
, където group_identifier
е число или име на група
/(?<word>\w+), \k<word>/
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/.match 'Today is 2011-11-08, Tuesday.'
# #<MatchData "2011-11-08" year:"2011" month:"11" day:"08">
/(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\11/.match 'Regular expressions'
# #<MatchData "ular express" 1:"u" 2:"l" 3:"a" 4:"r" 5:" " 6:"e" 7:"x" 8:"p" 9:"r" 10:"e" 11:"s">
/(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\k<11>1/.match 'Regular express1ions'
# #<MatchData "ular express1" 1:"u" 2:"l" 3:"a" 4:"r" 5:" " 6:"e" 7:"x" 8:"p" 9:"r" 10:"e" 11:"s">
/(\w+), \1/.match 'testing, testing' # #<MatchData "testing, testing" 1:"testing">
/(\w+), \1/.match 'testing, twice' # nil
/(?<word>\w+), \k<word>/.match 'testing, testing' # #<MatchData "testing, testing" word:"testing">
\g<name>
, където name
е номер или име на група в шаблона
/(\w+), \1/.match 'testing, twice' # nil
/(\w+), \g<1>/.match 'testing, twice' # #<MatchData "testing, twice" 1:"twice">
Да валидирате изрази от следния тип за правилно отворени/затворени скоби:
(car (car (car ...)))
- Например:
(car (car (car (car list))))
- Целта е израз, чийто резултат да може да се ползва в условен оператор (
true
/false
-еквивалент)- Можете да ползвате произволни методи от класа
Regexp
- И регулярен израз, разбира се
validator = /^(\(car \g<1>*\w*\))*$/
valid = '(car (car (car (car list))))'
invalid = '(car (car (car list))'
validator.match(valid) ? true : false # true
validator.match(invalid) ? true : false # false
/(?=pattern)/
/(?!pattern)/
/(?<=pattern)/
/(?<!pattern)/
/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>") # #<MatchData "bold">
Regexp#match
$~
Regexp.last_match
Enumerable
MatchData#[група]
, където група
е номер или име на група, ви връща порцията текст, отговаряща на съответната група
MatchData#begin(група)
пък ви връща число — отместването спрямо началото на низа на порцията текст, отговаряща на съответната група
/(\w+)/.match('Some words')[1] # "Some"
/(\w+)/.match('Some words').begin(1) # 0
/(?<id>\d+)/.match('ID: 12345')[:id] # "12345"
/(?<id>\d+)/.match('ID: 12345').begin(:id) # 4
MatchData#pre_match
(същото като специалната променлива $`
) — текстът преди съвпадението
MatchData#post_match
(същото като специалната променлива $'
) — текстът след съвпадението
match = /(?<number>\d+)/.match 'ID: 12345 (new)'
match[:number] # "12345"
match.pre_match # "ID: "
match.post_match # " (new)"
$~
, $'
, $1
, $2
, $3
и прочее
match
Regexp#match
=~
и !~
— дефинирани в Regexp
и в String
/pattern/ =~ 'Some string'
'Some string' =~ /pattern/
nil
, ако няма съвпадение, или число (offset), ако има такова
if
log_entry = "[2011-07-22 15:42:12] - GET / HTTP/1.1 200 OK"
if log_entry =~ /\bHTTP\/1.1 (\d+)/
request_status = $1.to_i # 200
else
raise "Malformed log entry!"
end
html = '<h1>Header</h1>' # или:
html = '<img src="http://my/image.src" alt="Kartman Makes Burgers" />'
case html
when /(<h(\d)>)(.+)<\/h\2>/ then {header: $3, size: $2}
when /<a\s+href="([^"]+)">([^<]+)<\/a>/ then {url: $1, text: $2}
when /<img\s+src="([^"]+)"\s+alt="([^"]+)"\s*\/>/ then {image: $1, alt: $2}
else 'unrecognized tag'
end
# {:image=>"http://my/image.src", :alt=>"Kartman Makes Burgers"}
String#match
String#=~
и String#!=
String#sub
, String#gsub
и вариантите им с !
String#[]
и String#slice
- в някои от вариантите си приемат регулярен израз
String#index
и rindex
приемат и регулярен израз
String#partition
и rpartition
и други...'SomeTitleCase'.gsub /(^|[[:lower:]])([[:upper:]])/ do
[$1, $2.downcase].reject(&:empty?).join('_')
end
# "some_title_case"
Regexp#encoding
/something/u
за UTF-8
Rubyのお父さんはまつもとゆきひろさんです。
unicode_test = 'Rubyのお父さんはまつもとゆきひろさんです。'
/は[[:alpha:]]+さん/.match unicode_test # #<MatchData "はまつもとゆきひろさん"># ~> -:1: invalid multibyte char (US-ASCII)
# ~> -:1: invalid multibyte char (US-ASCII)
\b
в Unicode-текст работи, когато границата на думата е лесно определима
/\b[[:alpha:]]\b/.match 'това и онова' # #<MatchData "и">
Rubyのお父さんはまつもとゆきひろさんです。
?Например:
'Ruby no otousan ha Matsumoto Yukihiro san desu.'.gsub(/(\b[[:alpha:]]+\b)/) { "[#{$1}]" }
# "[Ruby] [no] [otousan] [ha] [Matsumoto] [Yukihiro] [san] [desu]."
Но:
'Rubyのお父さんはまつもとゆきひろさんです。'.gsub(/(\b[[:alpha:]]+\b)/) { "[#{$1}]" }
# "[Rubyのお父さんはまつもとゆきひろさんです]。"
/pattern/flags
i
прави търсенето на съвпадение нечувствително към регистъра на буквите
u
кара шаблона да носи задължителна кодировка UTF-8
m
превръща шаблона в multiline-такъв (в този режим, например, .
ще съвпада и с нов ред)
Regexp
: http://www.ruby-doc.org/core-1.9.3/Regexp.html
MatchData
: http://www.ruby-doc.org/core-1.9.3/MatchData.html
ri
, например: ri Regexp#=~
RE: <моят въпрос>
, той ще го Google-не вместо вас и ще ви върне отговор в body-то на email-аСледващите слайдове са базирани основно на код, видян в първия ви опит да решите трета задача
UpperCamelCase
по конвенция
SCREAMING_SNAKE_CASE
по конвенцияdef MyClass.my_method
def self.my_method
Kernel#sprintf
; вместо това има String#%
, т.е.:
sprintf("| %-44s%2s | %8.2f |\n", @label, @quantity.to_s, calculate)
"| %-44s%2s | %8.2f |\n" % [@label, @quantity.to_s, calculate]
(@cart.coupon) ? @cart.coupon.calc_price : @cart.without_coupon
(discounted > 0) ? -discounted * @product.price * @percent * '0.01'.to_d : 0
@cart.coupon ? @cart.coupon.calc_price : @cart.without_coupon
discounted > 0 ? -discounted * @product.price * @percent * '0.01'.to_d : 0
if
-else
require
-директиви
@@promotion_list=[:get_one_free ,:package ,:threshold]
— noooo...return
на последния ред на метод
if not
са по-известни като unless
private # Private
— можете повече!
then
в стандартни if
-конструкции; например, избягвайте това:if (10...20).include?(cardinal) then
something...
end
Не:
if not promotion.empty?
new_promo.promo[new_product] = promotion.to_a
make_promoted(new_product)
else has_promotion[new_product] = false
end
Поне да е нещо такова:
if promotion.empty?
has_promotion[new_product] = false
else
new_promo.promo[new_product] = promotion.to_a
make_promoted(new_product)
end
Не ползвайте unless
с else
! Ако ви се налага, ползвайте if
-else
Плюс това, идентация...
unless inventory.new_promo.promo[product].kind_of? Hash
inventory.new_promo.get_one_free(product, one_s_price, quantity, value)
else inventory.new_promo.promo_type(product, one_s_price, quantity, pack, value)
end
Ох...
def execute(amount,price)
return calculate_get_one_free(amount,price) if @name == :get_one_free
return calculate_package(amount,price) if @name == :package
return calculate_threshold(amount,price) if @name == :threshold
end
Ма-а-алко по-добре:
def execute(amount, price)
case @name
when :get_one_free then calculate_get_one_free(amount, price)
when :package then calculate_package(amount, price)
when :threshold then calculate_threshold(amount, price)
end
end
Или пък:
def execute(amount, price)
send "calculate_#{@name}", amount, price
end
За това ще си говорим по-нататък; не е непременно добра практика :)
class ShopCar
def shop_car()
@shop_car = {}
end
ShopCar
!?
class MyClass
@shop_car = ...
:)cena = total
t = '0.00'.to_d
helper = inventory.all_coupons[name_of_coupon]
t = helper[0] == :percent ? cpn.percent(cena, helper[1]) : cpn.amount(cena, helper[1])
# съжалявам за съкращенията, но трябваше да се сместя в sceptic
Можете повече, вярваме във вас :)
def function(w, x, y, z)
- ( ( ( w - x ) * y.to_d ) * ( z / 100 ))
end
Keeewl... А какво точно правеше този метод? Хм...
class Numeric
def ordinal
cardinal = self.to_i.abs
if (10...20).include?(cardinal) then
cardinal.to_s << 'th'
else
cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal % 10]
end
end
end
cardinal.to_s << %w{th st nd rd th th th th th th}[cardinal % 10]
? Интересно, но...
th
, th
, th
, ...def package(product, one_s_price, quantity, pack, value)
out_of_pack = quantity % pack
if promo[product].has_key?(:package) and quantity >= pack
return function(quantity, out_of_pack, one_s_price, value)
else return '0.00'.to_d
end
end
def package(product, one_s_price, quantity, pack, value)
out_of_pack = quantity % pack
if promo[product].has_key?(:package) and quantity >= pack
a_better_named_function(quantity, out_of_pack, one_s_price, value)
else
'0.00'.to_d
end
end
raise 'Give me a name, not a novell!' if item_name.length > 40
— novel се пише с едно l