Reputation: 611
I have the following XML "device_google_data.xml"
:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<report>
<report-name name="Last 7 days CRITERIA_PERFORMANCE_REPORT" />
<date-range date="Mar 6, 2015" />
<table>
<columns>
<column name="campaign" display="Campaign" />
<column name="convertedClicks" display="Converted clicks" />
<column name="impressions" display="Impressions" />
<column name="clicks" display="Clicks" />
<column name="cost" display="Cost" />
<column name="device" display="Device" />
</columns>
<row campaign="The Winds at Mattern Orchard" convertedClicks="0" impressions="46" clicks="1" cost="3120000" device="Mobile devices with full browsers" />
<row campaign="Aberdeen Crossings" convertedClicks="0" impressions="72" clicks="1" cost="4260000" device="Mobile devices with full browsers" />
<row campaign="Hawthorne Woods" convertedClicks="0" impressions="147" clicks="0" cost="0" device="Computers" />
<row campaign="The Winds at Mattern Orchard" convertedClicks="0" impressions="115" clicks="0" cost="0" device="Computers" />
<row campaign="The Winds at Mattern Orchard" convertedClicks="0" impressions="13" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Southwest Commons" convertedClicks="0" impressions="9" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Westlake Woods" convertedClicks="0" impressions="12" clicks="1" cost="4480000" device="Tablets with full browsers" />
<row campaign="Beachwood Commons" convertedClicks="0" impressions="303" clicks="5" cost="21870000" device="Mobile devices with full browsers" />
<row campaign="Richland Woods" convertedClicks="0" impressions="24" clicks="0" cost="0" device="Mobile devices with full browsers" />
<row campaign="Westlake Woods" convertedClicks="0" impressions="24" clicks="1" cost="4040000" device="Mobile devices with full browsers" />
<row campaign="Salida Woods" convertedClicks="0" impressions="29" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Southwest Commons" convertedClicks="0" impressions="42" clicks="0" cost="0" device="Mobile devices with full browsers" />
<row campaign="Southwoods" convertedClicks="0" impressions="38" clicks="0" cost="0" device="Computers" />
<row campaign="Beachwood Commons" convertedClicks="0" impressions="50" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Salida Woods" convertedClicks="0" impressions="146" clicks="4" cost="14030000" device="Mobile devices with full browsers" />
<row campaign="Aberdeen Crossings" convertedClicks="0" impressions="168" clicks="1" cost="2530000" device="Computers" />
<row campaign="Beachwood Commons - BRAND" convertedClicks="0" impressions="2" clicks="1" cost="800000" device="Mobile devices with full browsers" />
<row campaign="Beachwood Commons - BRAND" convertedClicks="0" impressions="1" clicks="2" cost="240000" device="Computers" />
<row campaign="Hawthorne Woods" convertedClicks="0" impressions="21" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Hawthorne Woods" convertedClicks="0" impressions="103" clicks="4" cost="14870000" device="Mobile devices with full browsers" />
<row campaign="Aberdeen Crossings" convertedClicks="0" impressions="24" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Richland Woods" convertedClicks="0" impressions="3" clicks="1" cost="3550000" device="Tablets with full browsers" />
<row campaign="Salida Woods" convertedClicks="0" impressions="211" clicks="3" cost="8760000" device="Computers" />
<row campaign="Southwest Commons" convertedClicks="0" impressions="39" clicks="1" cost="7320000" device="Computers" />
<row campaign="Richland Woods" convertedClicks="0" impressions="23" clicks="2" cost="6990000" device="Computers" />
<row campaign="Beachwood Commons" convertedClicks="0" impressions="467" clicks="2" cost="7060000" device="Computers" />
<row campaign="Westlake Woods" convertedClicks="0" impressions="54" clicks="0" cost="0" device="Computers" />
<row campaign="Southwoods" convertedClicks="0" impressions="9" clicks="0" cost="0" device="Tablets with full browsers" />
<row campaign="Southwoods" convertedClicks="0" impressions="37" clicks="1" cost="2980000" device="Mobile devices with full browsers" />
</table>
</report>
I'm trying to parse it and convert it to a hash. I'm close to getting what I want with each_with_index
#Parse device_file
device_file = File.open("device_google_data.xml")
doc = Nokogiri::XML(device_file)
rows = doc.css('row').map{ |row| Hash[ row.attributes.map{|n,a| [n,a.value]} ] }
campaigns = rows.map {|m| m["campaign"]}
device = rows.map {|m| m["device"]}
impressions = rows.map {|m| m["impressions"]}.map{|e| e.to_i}
clicks = rows.map {|m| m["clicks"]}.map {|m| m.to_i}
conversions = rows.map {|m| m["convertedClicks"]}.map {|m| m.to_i}
cost = rows.map {|m| m["cost"]}.map {|m| m.to_f}.map{|c| c / 1000000}
Construct Hash
device_hash = {}
campaigns.each_with_index { |e, i|
device_hash[e.to_sym] = {impressions: impressions[i], clicks: clicks[i], conversions: conversions[i], cost: cost[i], device: device[i]}
}
However, it only gives me one instance each of campaign
. Its similar to calling uniq
on an array. I wanted all the campaign rows mapped.
device_hash = {:"The Winds at Mattern Orchard"=>{:impressions=>13, :clicks=>0, :conversions=>0, :cost=>0.0, :device=>"Tablets with full browsers"}, :"Aberdeen Crossings"=>{:impressions=>24, :clicks=>0, :conversions=>0, :cost=>0.0, :device=>"Tablets with full browsers"}, :"Hawthorne Woods"=>{:impressions=>103, :clicks=>4, :conversions=>0, :cost=>14.87, :device=>"Mobile devices with full browsers"}, :"Southwest Commons"=>{:impressions=>39, :clicks=>1, :conversions=>0, :cost=>7.32, :device=>"Computers"}, :"Westlake Woods"=>{:impressions=>54, :clicks=>0, :conversions=>0, :cost=>0.0, :device=>"Computers"}, :"Beachwood Commons"=>{:impressions=>467, :clicks=>2, :conversions=>0, :cost=>7.06, :device=>"Computers"}, :"Richland Woods"=>{:impressions=>23, :clicks=>2, :conversions=>0, :cost=>6.99, :device=>"Computers"}, :"Salida Woods"=>{:impressions=>211, :clicks=>3, :conversions=>0, :cost=>8.76, :device=>"Computers"}, :Southwoods=>{:impressions=>37, :clicks=>1, :conversions=>0, :cost=>2.98, :device=>"Mobile devices with full browsers"}, :"Beachwood Commons - BRAND"=>{:impressions=>1, :clicks=>2, :conversions=>0, :cost=>0.24, :device=>"Computers"}}
Upvotes: 0
Views: 36
Reputation: 191
I'm not sure I understood your question.
You got all the campaign rows mapped at this point:
campaigns = rows.map {|m| m["campaign"]}
The campaigns array has 29 elements.
But then you iterate this list and put them in a hash with the campaign name as key:
campaigns.each_with_index { |e, i|
device_hash[e.to_sym] = {impressions: impressions[i], clicks: clicks[i], conversions: conversions[i], cost: cost[i], device: device[i]}
}
This is the point where the number of rows gets reduced as there are campaigns with the same name, thus evaluating to the same hash bucket.
If you want to have all the rows in an object you could use an array instead of a hash. Or you could use an aggregate function when building the hash, summing up values for example.
campaigns.each_with_index { |e, i|
prev = device_hash[e.to_sym]
if (prev.blank?)
device_hash[e.to_sym] = {:impressions => impressions[i], :clicks => clicks[i], :conversions => conversions[i], :cost => cost[i], :device => device[i]}
else
prev[:impressions] += impressions[i]
prev[:clicks] += clicks[i]
prev[:conversions] += conversions[i]
prev[:cost] += cost[i]
prev[:device] << " | #{device[i]}"
end
}
I hope it helps.
Upvotes: 1