[英]Ruby Parsing an array of string
這是一個解析紅寶石中的簡單字符串的簡單代碼
str = "Amdh#34HB!x"
length = str.length
upper = str.scan(/[A-Z]/).count #count upper chars
lower = str.scan(/[a-z]/).count #count lower chars
digit = str.scan(/[0-9]/).count #count digits
special = str.scan(/[^a-z0-9]/i).count #count special chars
result = "Length : " + length.to_s + " Upper : " + upper.to_s + " Lower : " + lower.to_s + " Digit : " + digit .to_s + " Special : " + special.to_s
結果為"Length : 11 Upper : 3 Lower : 4 Digit : 2 Special : 2"
我想對字符串數組做同樣的事情
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"]
所以我可以知道數組每個元素的細節
范例:
array[0] = "Length : 11 Upper : 3 Lower : 4 Digit : 2 Special : 2"
array[1] = "Length : 8 Upper : 3 Lower : 3 Digit : 2 Special : 0"
array[2] = "Length : 8 Upper : 1 Lower : 3 Digit : 3 Special : 1"
....
我知道通過使用each
方法,答案似乎很簡單,但是沒有找到正確的方法。
上面的代碼未優化,如果有更好的建議,歡迎您!
您可以使用簡單的map
執行此操作:
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"]
result = array.map do |str|
length = str.length
upper = str.scan(/[A-Z]/).count #count upper chars
lower = str.scan(/[a-z]/).count #count lower chars
digit = str.scan(/[0-9]/).count #count digits
special = str.scan(/[^a-z0-9]/i).count #count special chars
{length: length, upper: upper, lower: lower, digit: digit, special: special}
end
[117] pry(main)> result
=> [{:length=>11, :upper=>3, :lower=>4, :digit=>2, :special=>2},
{:length=>8, :upper=>3, :lower=>3, :digit=>2, :special=>0},
{:length=>8, :upper=>1, :lower=>3, :digit=>3, :special=>1}]
您只需要對字符串進行一次遍歷即可獲得所需的計數。
def obtain_counts(str)
str.each_char.with_object(Hash.new(0)) do |c,h|
h[case(c)
when /[[:upper:]]/ then :upper
when /[[:lower:]]/ then :lower
when /[[:digit:]]/ then :digit
else :special
end] += 1
end
end
def construct_array(arr)
arr.map! { |str|
"Length : #{str.length} Upper : %d Lower : %d Digit : %d Special : %d" %
obtain_counts(str).values_at(:upper, :lower, :digit, :special) }
end
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"]
construct_array(array)
#=> ["Length : 11 Upper : 3 Lower : 4 Digit : 2 Special : 2",
# "Length : 8 Upper : 3 Lower : 3 Digit : 2 Special : 0",
# "Length : 8 Upper : 1 Lower : 3 Digit : 3 Special : 1"]
array
#=> ["Length : 11 Upper : 3 Lower : 4 Digit : 2 Special : 2",
# "Length : 8 Upper : 3 Lower : 3 Digit : 2 Special : 0",
# "Length : 8 Upper : 1 Lower : 3 Digit : 3 Special : 1"]
注意
["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"].map { |str| obtain_counts(str) }
#=> [{:upper=>3, :lower=>4, :special=>2, :digit=>2},
# {:upper=>3, :lower=>3, :digit=>2},
# {:special=>1, :digit=>3, :upper=>1, :lower=>3}]
注意,此數組中的第二個哈希沒有key :special
(因為第二個字符串不包含特殊字符)。 這就解釋了為什么在obtain_counts
,我們需要Hash.new(0)
(默認0
空哈希),而不是簡單的{}
。
我想您想這樣做:
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"]
result = []
array.each do |str|
length = str.length
upper = str.scan(/[A-Z]/).count #count upper chars
lower = str.scan(/[a-z]/).count #count lower chars
digit = str.scan(/[0-9]/).count #count digits
special = str.scan(/[^a-z0-9]/i).count #count special chars
result << "Length : " + length.to_s + " Upper : " + upper.to_s + " Lower : " + lower.to_s + " Digit : " + digit .to_s + " Special : " + special.to_s
end
puts result
更多DRY解決方案:
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"]
formats = { Upper: /[A-Z]/,
Lower: /[a-z]/,
Digit: /[0-9]/,
Special: /[^a-z0-9]/i }
array.map do |e|
"Length: #{e.length}, " +
formats.map {|k, v| "#{k}: #{e.scan(v).count}" }.join(', ')
end
#=> ["Length: 11, Upper: 3, Lower: 4, Digit: 2, Special: 2",
# "Length: 8, Upper: 3, Lower: 3, Digit: 2, Special: 0",
# "Length: 8, Upper: 1, Lower: 3, Digit: 3, Special: 1"]
試試這個解決方案:
def string_check(str)
result = str.scan(/([A-Z])|([a-z])|([0-9])|([^a-z0-9])/).inject([0,0,0,0]) do
|sum,arr| sum.map.with_index{|e,i| e+(arr[i].nil? ? 0: 1) if !arr.nil?}
end
"Length : #{str.size} Upper : #{result[0]} Lower : #{result[1]} Digit : #{result[2]} Special : #{result[3]}"
end
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"]
array.each {|s| puts string_check(s)}
輸出:
Length : 11 Upper : 3 Lower : 4 Digit : 2 Special : 2
Length : 8 Upper : 3 Lower : 3 Digit : 2 Special : 0
Length : 8 Upper : 1 Lower : 3 Digit : 3 Special : 1
這是開始幫助您進入更多OO Ruby腳本的開始:
class Foo
attr_reader :str, :str_len, :upper, :lower, :digit, :punctuation
def initialize(str)
@str = str
@str_len = str.length
@upper, @lower, @digit, @punctuation = %w[upper lower digit punct].map { |re| str.scan(/[[:#{re}:]]/).count }
end
def to_s
('"%s": ' % str) +
[:str_len, :upper, :lower, :digit, :punctuation].map { |s|
'%s: %s' % [s.to_s.upcase, instance_variable_get("@#{s}")]
}.join(' ')
end
end
array = ["Amdh#34HB!x", "AzErtY45", "#1A3bhk2"].map { |s| Foo.new(s) }
puts array.map(&:to_s)
運行時輸出:
"Amdh#34HB!x": STR_LEN: 11 UPPER: 3 LOWER: 4 DIGIT: 2 PUNCTUATION: 2
"AzErtY45": STR_LEN: 8 UPPER: 3 LOWER: 3 DIGIT: 2 PUNCTUATION: 0
"#1A3bhk2": STR_LEN: 8 UPPER: 1 LOWER: 3 DIGIT: 3 PUNCTUATION: 1
諸如[[:upper:]]
類的正則表達式類是POSIX定義,可幫助減輕傳統表達式類的視覺干擾。 有關更多信息,請參見Regexp文檔 。
可以是DRYer,但這是學生的練習。 您應該能夠將其強制為更接近所需的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.