簡體   English   中英

Ruby解析字符串數組

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM