Get the count of duplicate keys in a hash - ruby

I have a hash say
test = [ {:a1=>"a", :b1=>"q"},
{:a1=>"c", :b1=>"z"},
{:a1=>"a", :b1=>"zcq"} ]
Need to find out count of key with "a" (e.g. :a1=>"a") in a hash. The output should be 2 if i am searching for key as "a".
How to find the count of the selected key.

Try this one
test.count { |item| item[:a1] == 'a' }

Related

Ruby: Hash w/ Arrays, Returning Associated Key If Value Is In Array

New to Ruby and have run out of ideas. I have an array of books that I would like to 1) Shelve 2) Find which shelf it is on 3) Remove it from the associated shelf if found. For brevity I have an array of 6 books. Each shelf contains 5 books.
library_catalog = [ "Book1", "Book2", "Book3", "Book4", "Book5", "Book6" ]
shelves = Hash.new(0)
catalog_slice = library_catalog.each_slice(5).to_a
count = 1
catalog_slice.each do | x |
shelves.merge!(count=>x)
count+=1
end
From this I know have a Hash w/ arrays as such
{1=>["Book1", "Book2", "Book3", "Book4", "Book5"], 2=>["Book6"]}
This is where I'm having trouble traversing the hash to find a match inside the array and return the key(shelf). If I have title = "Book1" and I am trying to match and return 1, how would I go about this?
I think this should work.
shelves.select { |k,v| v.include?("Book1")}.keys.first
selected the hashes that have a value equal to the title you are looking for (in this case "Book1")
get the keys for these hashes as an array
get the first entry in the array.
to remove the Book from the shelf try this:
key = shelves.select { |k,v| v.include?("Book1")}.keys.first
shelves[key].reject! { |b| b == "Book1" }
get a reference to the array and then reject the entry you want to remove

Combining multiple array/hash selects

I have the following code:
sum = array_of_hashes.select{ |key| (date_range).include? Date.parse(key[:created])}.map { |h| h[:amount] }.sum
size = array_of_hashes.select{ |key| (date_range).include? Date.parse(key[:created])}.size
total = sum / size
sum selects all hashes with a date that is inside a date range and the adds up all the values of the :amount key.
size counts the number of hashes that are in the date range.
total divides the sum by the size.
How can I combine those so it's not 3 separate items?
I think it's as simple as:
selected = array_of_hashes.select { ... }
avarage = selected.map { ... }.sum / selected.size
Note: using include? with ranges of dates is pretty inefficient since it needs to traverse the whole dates range, I suggest to use cover? instead.
There is really no nice way of doing this more compact. One alternative could be the following:
average = (selected = array_of_hashes.select { ... }.map { ... }).sum/selected.size.to_f

Most efficient way to extract an item from a Ruby array of hashes

I have some large Ruby structures that I need to quickly extract data from. I have no control over the format of the data, although I'm open to transforming it under certain circumstances. What is the most efficient way to extract a single item from the following hash, when using the displayName as the 'key'.
[
{'displayName'=>'Some Key 1', 'values'=>[1,2,3]},
{'displayName'=>'Some Key 2', 'values'=>["Some text"]},
{'displayName'=>'Some Key 3', 'values'=>["Different text","More text"]},
{'displayName'=>'Some Key 4', 'values'=>[2012-12-12]}
]
Each hash has other keys in it that I've removed to assist understanding.
The challenge is that in certain circumstances, the displayName field will need to be matched on a prefix sub-string. Does anybody have any practical experience knowing when to use .each and match manually, or .select to get the common case exact matches and fallback for the prefixes afterwards. Or is there some common trick I'm missing.
If you're doing this once, you'll probably just have to iterate over the set and find what you need:
row = data.find do |row|
row['displayName'] == name
end
row && row['values']
If you're doing it more than once, you should probably make an indexed structure out of it with a simple transform to create a temporary derivative structure:
hashed = Hash[
data.collect do |row|
[ row['displayName'], row['values'] ]
end
]
hashed[name]
You can use simple select thought it may no be as fast as it could with large sized arrays:
data = [
{'displayName'=>'Some Key 1', 'values'=>[1,2,3]},
{'displayName'=>'Some Key 2', 'values'=>["Some text"]},
{'displayName'=>'Some Key 3', 'values'=>["Different text","More text"]},
{'displayName'=>'Some Key 4', 'values'=>[2012-12-12]}
]
data.select { |e| e['displayName'] == 'Some Key 2' }.first
You can group_by the desired key instead, wich will make access faster
hashed_data = data.group_by { |e| e['displayName'] }
hashed_data['Some Key 4']
=> [{"displayName"=>"Some Key 4", "values"=>[1988]}]

Set array elements (string) as variable name in Ruby

I have the following array, that I use to later write the header on an Excel file.
fields = ["fileName", "type", "id"]
And then I have the following code that reads values from an XML:
filename = xml.xpath('//path/filename').text
type = xml.xpath('//path/type').text
id = xml.xpath('//path/id').text
The I iterate the initial array (fields) in order to set the Excel cells to the values extracted in the previous step:
row = 2
c = 1
fields.each do |content|
ws.Cells(row,c).Value = content
c = c + 1
I'm trying to have the array's (fields) contents to variable names instead of strings in order to be able to reuse the head fields.
Can anyone recommend a way of making it possible?
This sounds like you need to use a Hash to associate field names to the values you extracted:
fields = {
"fileName" => xml.xpath('//path/filename').text,
"type" => xml.xpath('//path/type').text,
"id" => xml.xpath('//path/id').text
}
row=2
c=1
fields.each do |key,value|
ws.Cells(row,c).Value = value
c=c+1
end

Lua - Sorting a table alphabetically

I have a table that is filled with random content that a user enters. I want my users to be able to rapidly search through this table, and one way of facilitating their search is by sorting the table alphabetically. Originally, the table looked something like this:
myTable = {
Zebra = "black and white",
Apple = "I love them!",
Coin = "25cents"
}
I was able to implement a pairsByKeys() function which allowed me to output the tables contents in alphabetical order, but not to store them that way. Because of the way the searching is setup, the table itself needs to be in alphabetical order.
function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do
table.insert(a, n)
end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
return a[i], t[a[i]]
end
end
return iter
end
After a time I came to understand (perhaps incorrectly - you tell me) that non-numerically indexed tables cannot be sorted alphabetically. So then I started thinking of ways around that - one way I thought of is sorting the table and then putting each value into a numerically indexed array, something like below:
myTable = {
[1] = { Apple = "I love them!" },
[2] = { Coin = "25cents" },
[3] = { Zebra = "black and white" },
}
In principle, I feel this should work, but for some reason I am having difficulty with it. My table does not appear to be sorting. Here is the function I use, with the above function, to sort the table:
SortFunc = function ()
local newtbl = {}
local t = {}
for title,value in pairsByKeys(myTable) do
newtbl[title] = value
tinsert(t,newtbl[title])
end
myTable = t
end
myTable still does not end up being sorted. Why?
Lua's table can be hybrid. For numerical keys, starting at 1, it uses a vector and for other keys it uses a hash.
For example, {1="foo", 2="bar", 4="hey", my="name"}
1 & 2, will be placed in a vector, 4 & my will be placed in a hashtable. 4 broke the sequence and that's the reason for including it into the hashtable.
For information on how to sort Lua's table take a look here: 19.3 - Sort
Your new table needs consecutive integer keys and needs values themselves to be tables. So you want something on this order:
SortFunc = function (myTable)
local t = {}
for title,value in pairsByKeys(myTable) do
table.insert(t, { title = title, value = value })
end
myTable = t
return myTable
end
This assumes that pairsByKeys does what I think it does...

Resources