From: "ara.t.howard" Date: 2008-07-31T03:15:22+09:00 Subject: Re: Suggestions for improving a trivial tag parser On Jul 30, 2008, at 11:28 AM, Gregory Brown wrote: > Hi folks, > > I need to take strings that have embedded and tags and split > them out into an array. > Here are some examples: > > # No need to ensure valid pairs, just need to break out tags from > the text > #---------------------------------------------------------------------------------------------- > > describe "Inline style parsing" do > it "should return an identical string if inline styles are not > detected" do > create_pdf > @pdf.parse_inline_styles("Hello World").should == "Hello World" > end > > it "should return an array of segments when a style is detected" do > create_pdf > @pdf.parse_inline_styles("Hello Fine World").should == > ["Hello ", "","Fine", "", " World"] > end > > it "should create an array of segments when multiple styles are > detected" do > create_pdf > @pdf.parse_inline_styles("Hello Fine World").should > == > ["Hello ", "", "Fine ", "", "World", "", ""] > end > end > > ### > > I fear my implementation (below) is showing one of my weakest areas in > Ruby, and probably even has some unforeseen problems. I'm sure it can > be done more accurately in less code. Any kind RubyTalk folks want to > school me? > > ### > > def parse_inline_styles(text) #:nodoc: > require "strscan" > > sc = StringScanner.new(text) > output = [] > last_pos = 0 > > loop do > if sc.scan_until(/<\/?[ib]>/) > pre = sc.pre_match[last_pos..-1] > output << pre unless pre.empty? > output << sc.matched > last_pos = sc.pos > else > output << sc.rest if sc.rest? > break output > end > end > > output.length == 1 ? output.first : output > end > > ### > > Thanks, > -greg > my take: cfp:~ > cat a.rb require 'yaml' strings = "Hello World", "Hello Fine World", "Hello Fine World" def parse_inline_styles string, tags = %w( ) re = Regexp.new tags.flatten.map{|tag| "(#{ Regexp.escape tag })"}.join('|') tokens = string.split(re) tokens.delete_if{|token| token.empty?} ((tokens.size == 1 and tokens.first == string) ? string : tokens) end strings.each do |string| y string => parse_inline_styles(string) end cfp:~ > ruby a.rb --- Hello World: Hello World --- Hello Fine World: - "Hello " - - Fine - - " World" --- Hello Fine World: - "Hello " - - "Fine " - - World - - a @ http://codeforpeople.com/ -- we can deny everything, except that we have the possibility of being better. simply reflect on that. h.h. the 14th dalai lama