[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

array of hashes - need to iterate and calulate stats but how

Adam Akhtar

8/20/2008 10:30:00 AM

I making a script which generates some basic stats for completed
listings on ebay. Its merely a means to improve on my ruby so its pretty
primitive ;)

I have an array of hashes. Each hash represents a listing on ebay.
e.g.
{:title => "Canon Accessory R45-WD45", :model_number =>"R45-WD45"
:did_it_sell => TRUE}

Within in the array there will be many listings for the same product.
E.g. 25 wiis, 45 xboxes 35 sigma 18-50mm lenses etc.

I want to work out statistics for each product grouping. Teh desired
output would be something like this

Wii - Total listings 25. Total sold 10. Sell through rate 40%
Xbox - Total listings 50. Total sold 2. Sell through rate 4%

So i need to at least sort the array of products in order of their model
number passing sort a custom block.

From here on im not sure how to proceed. Should I bundle the groupings
of model numbers into their own arrays or should i simply iterate over
this nicely sorted array and make the script keep a mental note of what
product its calculating for.

in C i would have used a structure to contain the product information.
Is a hash the best thing to use?

Im not looking for someone to write the code but rather a general
outline of how this type of stuff is usually done. any help greatly
apprecated.
--
Posted via http://www.ruby-....

18 Answers

Lex Williams

8/20/2008 10:41:00 AM

0

something like this :

statistic_hash = {}

array.each do |hash|
if(hash[:did_it_sell)
if(statistic_hash.has_key? hash[:title]
statistic_hash[hash[:title]] += 1
else
statistic_hash[hash[:title]] = 0
end
end
end

and then you would have a statistic_hash containing as key a product
name , and as value , the number of units sold. I'm not sure about how
to calculate the statistics .

I'm a ruby newbie , so I hope this was helpful :)
--
Posted via http://www.ruby-....

Adam Akhtar

8/20/2008 11:18:00 AM

0

Thanks for the response,

your solution would be great but the problem is i cant use a hash to
store the output as I need to store more than two values. I need to have
model number, total listed, total sold and finaly the sell through rate
based on the previous two numbers.

Ive tried to rejig teh general jist of your approach but couldnt.

Heres my very rough solution. Surely theres a more elegant way to this

number_listed = 0
number_sold = 0
current_model = item_info[0][:unique_identifier]
item_info.each do |item|
if current_model != item[:unique_identifier]
result = {unique_identifier => current_model, :total_listings
=> number_listed, :total_sold => number_sold, :str =>
number_sold/number_listed*100.00}
number_sold = 0
numbler_listed = 0
unique_identifier = item[:unique_identifier]
end
number_sold += if item[:did_it_sell]
number_listed +=
end


--
Posted via http://www.ruby-....

Adam Akhtar

8/20/2008 11:20:00 AM

0

unique_identifier in the above code is merely refers to the model
number.
--
Posted via http://www.ruby-....

David A. Black

8/20/2008 11:29:00 AM

0

Hi --

On Wed, 20 Aug 2008, Adam Akhtar wrote:

> I making a script which generates some basic stats for completed
> listings on ebay. Its merely a means to improve on my ruby so its pretty
> primitive ;)
>
> I have an array of hashes. Each hash represents a listing on ebay.
> e.g.
> {:title => "Canon Accessory R45-WD45", :model_number =>"R45-WD45"
> :did_it_sell => TRUE}
>
> Within in the array there will be many listings for the same product.
> E.g. 25 wiis, 45 xboxes 35 sigma 18-50mm lenses etc.
>
> I want to work out statistics for each product grouping. Teh desired
> output would be something like this
>
> Wii - Total listings 25. Total sold 10. Sell through rate 40%
> Xbox - Total listings 50. Total sold 2. Sell through rate 4%
>
> So i need to at least sort the array of products in order of their model
> number passing sort a custom block.
>
>> From here on im not sure how to proceed. Should I bundle the groupings
> of model numbers into their own arrays or should i simply iterate over
> this nicely sorted array and make the script keep a mental note of what
> product its calculating for.
>
> in C i would have used a structure to contain the product information.
> Is a hash the best thing to use?

You could probably generate a report fairly easily in this case with
hash and array manipulation, but in general, in cases where you'd be
likely to create a structure in C, in Ruby you'd typically write a
class that has the attributes and methods you need. So maybe something
like this:

class Item
attr_reader :title, :model_number, :sold

def initialize(hash)
@title, @model_number, @sold = hash.values_at(:title,
:model_number, :did_it_sell)
end

def <=>(other)
model_number <=> other.model_number
end
end

and then if you have an array of hashes you can turn it into an array
of items:

items = hashes.map {|h| Item.new(h) }

and then items.sort will be sorted by model number (because of the <=>
definition in Item).


David

--
Rails training from David A. Black and Ruby Power and Light:
Advancing With Rails August 18-21 Edison, NJ *
Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
Advancing with Rails January 19-22 Fort Lauderdale, FL
* Co-taught by D.A. Black and Erik Kastner
See http://www.r... for details and updates!

David A. Black

8/20/2008 11:32:00 AM

0

Hi --

On Wed, 20 Aug 2008, Lex Williams wrote:

> something like this :
>
> statistic_hash = {}
>
> array.each do |hash|
> if(hash[:did_it_sell)
> if(statistic_hash.has_key? hash[:title]
> statistic_hash[hash[:title]] += 1
> else
> statistic_hash[hash[:title]] = 0
> end
> end
> end
>
> and then you would have a statistic_hash containing as key a product
> name , and as value , the number of units sold. I'm not sure about how
> to calculate the statistics .

You can use a hash with a default value to make all that hash testing
easier:

statistic_hash = Hash.new(0)
array.each do |hash|
next unless hash[:did_it_sell]
statistic_hash[hash[:title]] += 1
end


David

--
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
Advancing with Rails January 19-22 Fort Lauderdale, FL
See http://www.r... for details and updates!

Lex Williams

8/20/2008 11:42:00 AM

0

David A. Black wrote:
> Hi --
>
> On Wed, 20 Aug 2008, Lex Williams wrote:
>
>> end
>> end
>> end
>>
>> and then you would have a statistic_hash containing as key a product
>> name , and as value , the number of units sold. I'm not sure about how
>> to calculate the statistics .
>
> You can use a hash with a default value to make all that hash testing
> easier:
>
> statistic_hash = Hash.new(0)
> array.each do |hash|
> next unless hash[:did_it_sell]
> statistic_hash[hash[:title]] += 1
> end
>
>
> David

you could use select on the array , and lose those if's . something like
this :

array.select { |hash| hash[:did_it_sell] }.each do |hash|
statistic_hash[hash[:title]] += 1
end
--
Posted via http://www.ruby-....

Adam Akhtar

8/20/2008 11:46:00 AM

0

hi guys thanks for the advice. id like to stick with processing a hash
rather htan a class for the moment.

The problme is the output object cant be a hash, it would have to be an
array of hashes as in my reply to lex ill want to return more than two
values for each item.

ill need the model number, the total nubmer of listings for that model,
the number of which sold and from those the sell through rate
(percentage that sold).

With a hash i can only have a key and a value which is a shame as those
solutions above looked good. I cant think of a way to rejig them to work
with an array of hashes.

or is my assumption wrong.
--
Posted via http://www.ruby-....

Lex Williams

8/20/2008 11:49:00 AM

0

adam , how about an array ref as the value for a certain key?
--
Posted via http://www.ruby-....

Adam Akhtar

8/20/2008 12:08:00 PM

0

hi lex,

im not so hot on ruby, could you expand on what you mean by that?

--
Posted via http://www.ruby-....

Thomas Wieczorek

8/20/2008 12:22:00 PM

0

You can also create Structs in Ruby if you prefer them

Item = Struct.new(:title, :article_number)
it = Item.new("Wii", "Wii")
it.title #=>"Wii"

You can add as many members as you like in the Struct constructor.

As to go with your statistics, I agree with the others. I'd use a
statitiscs Hash and count the different items:

stats_hash = { }
Stats = Struct.new(:count, :sold)
item_array.each { |it|
unless hash[item[:article_number]]
hash[item[:article_number]] = Stats.new(0, 0)
end
hash[item[:article_number]].count += 1
hash[item[:article_number]].sold += 1 if item[:did_it_sell]
}