开发者

Cleanest ruby code to split a string with specific rules

开发者 https://www.devze.com 2023-02-05 19:26 出处:网络
imagine an array like this [ \"A definition 1: this is the definition text\", \"A definition 2: this is some other definition text\",

imagine an array like this

[
"A definition 1: this is the definition text",
"A definition 2: this is some other definition text",
"B definition 3: this could be: the definition text"
]

I want to end up with the following hash

hash = {
:A => ["A definition 1", "this 开发者_开发知识库is the definition text", "A definition 2", "this is some other definition text"], 
:B => ["B definition 3", "this could be: the definition text"]
}

I'm creating a glossary, with a hash of each letter of the alphabet with definition arrays.

I'm pretty new to Ruby so what I have looks really inelegant and I'm struggling on the split regex of the line on the colon so that the 3rd line only splits on the first occurrence.

Thanks!

Edit Here's what I have so far

def self.build(lines)
    alphabet = Hash.new()

    lines.each do |line|
      strings = line.split(/:/)
      letter = strings[0][0,1].upcase
      alphabet[letter] = Array.new if alphabet[letter].nil?
      alphabet[letter] << strings[0]
      alphabet[letter] << strings[1..(strings.size-1)].join.strip
    end
    alphabet
  end


Provided raw_definitions is your input:

sorted_defs = Hash.new{|hash, key| hash[key] = Array.new;}

raw_definitions.each do |d|
  d.match(/^([a-zA-Z])(.*?):(.*)$/)
  sorted_defs[$1.upcase]<<$1+$2
  sorted_defs[$1.upcase]<<$3.strip
end


Just for fun, here's a purely-functional alternative:

defs = [
  "A definition 1: this is the definition text",
  "A definition 2: this is some other definition text",
  "B definition 3: this could be: the definition text"
]

hash = Hash[
  defs.group_by{ |s| s[0].to_sym }.map do |sym,strs|
    [ sym, strs.map{ |s| s[2..-1].split(/\s*:\s*/,2) }.flatten ]
  end
]

require 'pp'
pp hash
#=> {:A=>
#=>   ["definition 1",
#=>    "this is the definition text",
#=>    "definition 2",
#=>    "this is some other definition text"],
#=>  :B=>["definition 3", "this could be: the definition text"]}

And a not-purely-functional variation with the same results:

hash = defs.group_by{ |s| s[0].to_sym }.tap do |h|
  h.each do |sym,strs|
    h[sym] = strs.map{ |s| s[2..-1].split(/\s*:\s*/,2) }.flatten
  end 
end

Note that these solutions only work in Ruby 1.9 due to the use of s[0].to_sym; to work in 1.8.7 you would have to change this to s[0,1].to_sym. To make the first solution work in 1.8.6 you would further have to replace Hash[ xxx ] with Hash[ *xxx.flatten ]

0

精彩评论

暂无评论...
验证码 换一张
取 消