byCoder
byCoder

Reputation: 9184

How can I change data collection from hash to array?

Now I'm fetching data from another url... Here is my code:

require 'rubygems'
    require 'nokogiri'

    html = page.body

    doc = Nokogiri::HTML(html)
    doc.encoding = 'utf-8'

    rows = doc.search('//table[@id = "MainContent_GridView1"]//tr')
      @details = rows.collect do |row|
          detail = {}
          [
            [:car, 'td[1]/text()'],
            [:article, 'td[2]/text()'],
            [:group, 'td[3]/text()'],
            [:price, 'td[4]/text()'],
          ].each do |name, xpath|
            detail[name] = row.at_xpath(xpath).to_s.strip
          end
          detail
      end
    @details  

I tried to do it via array, not a hash. But I get a lot of errors... Are there any ideas? I need it for another method...

also i set data (this result hash) to another car here:

oem_art = []
    @constr_num.each do |o|
      as_oem = get_from_as_oem(o.ARL_SEARCH_NUMBER)
      if as_oem.present?
        oem_art << as_oem
      end
    end    

    @oem_art = oem_art.to_a.uniq

Upvotes: -1

Views: 203

Answers (2)

Rym
Rym

Reputation: 650

It looks like you're looking for something like hash['key'] to hash.key in Ruby

The Hash Class doesn't support .key notation by default, OpenStruct creates an Object from the Hash so you can use dot notation to access the properties. Overall it's basically just syntactic sugar with overhead.

Suggested code (from linked answer)

>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"

So in your example, you could do:

# Initialised somewhere
require 'ostruct'
DETAIL_INDICES = { 
  :car => 1,
  :article => 2,
  :group => 3,
  :price => 4,
}

# ** SNIP **
@details = rows.map do |row|
  DETAIL_INDICES.inject({}) do |h,(k,v)| 
    h.merge(k => row.at_xpath("td[#{v}]/text()").to_s.strip) 
  end
end.collect { |hash| OpenStruct.new hash }

@details.each do |item|
  puts item.car
end

Of course if performance is a concern you can merge your map&collect (They are the same), but this is just a minor separation for basic semantic differences, although I usually only use map for consistency, so feel free to choose yourself :)

EDIT -- Additional code from your edit simplified

@oem_art = @constr_num.select do |item|
  as_oem = get_from_as_oem(item.ARL_SEARCH_NUMBER)
  as_oem.present?
end

puts @oem_art.uniq

Upvotes: 0

user1454117
user1454117

Reputation:

Do you just want to change a hash into an array? If so, just use the to_a method on your hash.

hash = {:a => "something", :b => "something else"}
array = hash.to_a
array.inspect #=> [[:a, "something"], [:b, "something else"]]

Upvotes: 1

Related Questions