2011-01-21 2 views
1

представить массив как этотCleanest код рубин, чтобы разбить строку с определенными правилами

[ 
"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 = { 
: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"] 
} 

я создаю глоссарий, с хэш каждой буквы алфавита с массивами определений.

Я довольно новичок в Ruby, поэтому я выгляжу очень неэлегантно, и я борюсь с разделенным регулярным выражением линии на двоеточие, так что 3-я строка только разбивается на первое вхождение.

Спасибо!

Редактировать Вот что я до сих пор

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 
+1

Чтобы узнать, как использовать 'split()' только в первом случае, см. Мой ответ или, скорее, см. [Документация для 'split'] (http://ruby-doc.org/core/classes/String.html#M001165) и посмотрите на параметр' limit'. – Phrogz

+0

bah спасибо, что предел param ускользнул от меня до сих пор ... –

ответ

4

Прилагается raw_definitions это ваш вклад:

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 
+0

приятно в значительной степени сработало, $ 2 отсутствует $ 1, может ли вы снова начать второй матч в начале? –

+0

Да, вот почему я добавил $ 1 + $ 2 попробовать. Эта ревизия дает правильный результат, проверенный в IRB. –

2

Просто для удовольствия, вот чисто функциональной альтернативой:

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"]} 

И не чисто-фу nctional вариации с теми же результатами:

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 

Обратите внимание, что эти решения работают только в Ruby 1.9 из-за использования s[0].to_sym; для работы в 1.8.7 вам придется изменить это на s[0,1].to_sym. Для того чтобы первое решение работало в 1.8.6, вам также пришлось бы заменить Hash[ xxx ] на Hash[ *xxx.flatten ]

+0

ломает мой ноггин, читая его, но +1 для показа довольно проклятого крутого способа. –

+0

Это интересное решение, использующее нюансы рубинового языка. Спасибо, что поделился! –

Смежные вопросы