Hash mixed value type comparison - ruby-on-rails

I am trying to compare an Variable to a value within a hash, but the hash can be queried using both Numeric and String arguments.
ED_CONTRIBUTIONS = {
1 => {
db_code: 1,
name: 'Provision of housing and transport',
abbreviation: 'Provisions',
group: 'Social development contributions'
}
}
I use a method like this to do the comparison:
def find_item(field, value)
value.downcase if value.is_a? String
applicable_items.find { |k,v| v[field] == value}.andand.last || {}
end
but sometimes the v[filed] is the db_code and as a result a digit. how can i make it so that if v[field] is a string that it be downcased? or rather how does one check the state of the value of a hash in such an instance.

You can check if it's a string like this v[field].kind_of? String, and downcase it if it is.
Or you can just v[field].to_s.downcase it without checking the variable type.

You can just parse it to a String:
value.to_s.downcase
and then you don't need to investigate if the value is a String

Related

How to find the key in hash by a key within its nested hash

There is a nested hash, I need to find the first level key by the key inside of it. For instance,
hash = {
a: {
first: 0,
second: 1
},
b: {
third: 2
}
}
I am given :first and I need to find the key it belongs to, in this case it would be :a . Thanks in advance
If you wish to interrogate the hash multiple times, for different inner keys (:first, :second, and so on) you may wish to construct the following hash before the interrogations begin.
hash = { a: { first: 0, second: 1 }, b: { third: 2 } }
h = hash.each_with_object({}) { |(k,v),h| v.each { |kk,_| h[kk] = k } }
#=> {:first=>:a, :second=>:a, :third=>:b}
so that later you may simply do hash lookups:
h[:first]
#=> :a
If the hash could look like this:
hash = { a: { first: 0, second: 1 }, b: { third: 2, first: 3 } }
you may wish to define h as follows:
h = hash.each_with_object({}) do |(k,v),h|
v.each { |kk,_| h.update(kk=>[k]) { |_,o,n| o+n } }
end
#=> {:first=>[:a, :b], :second=>[:a], :third=>[:b]}
This uses the form of Hash#update (a.k.a. merge!) that employs a block (here { |_,o,n| o+n }) to determine the values of keys that are present in both hashes being merged. See the doc for explanations of the three block variables _, o and n. I used _ for the variable holding the common key to tell the reader that it is not used in the block calculations. That is common practice, though you might see, for example, _key in place of _.
You can use Enumerable#find and Hash#key?:
Hash[*hash.find { |_, value| value.key?(:first) }]
# {:a=>{:first=>0, :second=>1}}
Really, being a Hash it's possible you can have the same key in different hashes within the "main" hash, so probably select is an option as well.
You can extract the keys and then find the one for which hash has a key named :first:
hash.keys.find { |k| hash[k].key?(:first) }
#=> :a
Use select instead of find to get an array of all matching keys (if there can be multiple).

Convert string to XXX

In queel, I can do:
User.where{id.eq "2" | admin.eq true}
to query. I want to know if I can trans [sic] a string, which is a condition like:
string = "id: 2"
or
string = "id.eq '2' | admin.eq true"
and run:
User.where{string}
or
User.where(string)
The result is not a hash. How can I do that?
What you need is hash and not string. You can use it like this,
hash = {id: 2}
User.where(hash)
And if you really want to use string you can do it like this,
string = "id = 2"
User.where(string)
If you want to execute the string you can use eval. In that case it will be like this,
string = "{id: 2}"
User.where(eval string)
NB to use the variant below, one should read first five pages of Google output on query “ruby eval is evil.”
User.where(instance_eval("{#{string}}"))

Lua Changing Table Keys

Anyone tell me why this doesn't work?
GET_TABLE {1=ID}
key = string.format("%q", GET_TABLE[1])
RETURN_TABLE[key] = "ss"
print(RETURN_TABLE[ID])
print(GET_TABLE[1])
First print result: nil. Second print result: ID
I want the first print result to be: ss
GET_TABLE {1=ID}
key = "ID"
RETURN_TABLE[key] = "ss"
print(RETURN_TABLE[ID])
print(GET_TABLE[1])
The above works fine so I assume its due to the string.format not working right?
The %q format token returns the input as an escaped and quoted Lua string. This means that given the input ID it will return "ID" (the double quotes being part of the string!) which is a different string. (Or, represented as Lua strings, the input is 'ID' and the return value is '"ID"'.)
You have therefore set the ID key while trying to retrieve the "ID" key (which presumably does not exist).
> x = 'ID'
> =x
ID
> =string.format('%q', x)
"ID"
> =#x
2
> =#string.format('%q', x)
4
Your code does not compile (you need [] around the index), and you should use the raw string of ID, not the "quoted" string:
GET_TABLE = {[1]=ID}
key = string.format("%s", GET_TABLE[1])
Note that I had to initialize ID and RETURN_TABLE objects to the following:
ID = 'ID'
RETURN_TABLE = {}
Stylistic note: you should only use all-caps names for constants, otherwise too many makes code hard to read

Grails data binding to command object with maps - convert key to number

I have a Grails command object with a list of maps. The map key is intended to be a numeric domain object ID.
class MyCommand {
def grid = [].withDefault { [:] }
}
Data binding to the list/map is working in general because of the dynamic list expansion.
However, in the POST, the map keys are being bound as Strings and I want them to be Longs, as they are when the form is initially populated. I want foo[123] in my map, not foo['123'].
Alternatively I would be satisfied if the [] operators found the correct value given a numeric ID key to look up. In other words, if I could get foo[123] to return the same value as foo['123'], that would work too.
Any way to get this to work the way I want to? Maybe strongly type the map?
Or a better approach?
You can inject the property into the map to convert a String key to Long. For example:
def myMap = [:] << ['1': "name"] << ['Test': "bobo"]
def result = myMap.inject([:]){map, v ->
def newKey = v.key.isNumber() ? v.key.toLong() : v.key
map[newKey] = v.value
map
}
assert myMap['1'] == 'name'
assert result[1L] == 'name'
assert result['Test'] == 'bobo'

Lua: implicit table creation with string keys - why the extra brackets?

Say that you want to create a Lua table, and all its keys are valid lua identifiers. Then you can use the key=value syntax:
local niceTable = { I=1, like=1, this=1, syntax=1 }
If however your strings are not "identifiable", then you have to use the ['key']=value syntax:
local operators = { ['*']="Why", ['+']="the", ['/']="brackets", ['?']='?' }
I'm a bit baffled about this. What are those brackets doing there? What do they mean?
They identify the contained string as a key in the resulting table. The first form, you could consider as equal to
local niceTable = {}
niceTable.I = 1;
niceTable.like = 1;
The second form is equal to
local operators = {}
operators['*'] = "Why";
operators['+'] = "The";
The difference is purely syntactic sugar, except where the first one uses identifiers, so it has to follow the identifier rules, such as doesn't start with a number and interpret-time constant, and the second form uses any old string, so it can be determined at runtime, for example, and a string that's not a legal identifier. However, the result is fundamentally the same. The need for the brackets is easily explained.
local var = 5;
local table = {
var = 5;
};
-- table.var = 5;
Here, var is the identifier, not the variable.
local table = {
[var] = 5;
};
-- table[5] = 5;
Here, var is the variable, not the identifier.
The normal syntax for indexing a table is t[val]. For string keys only, Lua provides an alternate syntax, where t.foo is exactly equivalent to t["foo"]. This is purely a syntactical convenience, so-called 'syntax sugar'. It doesn't add functionality, it just gives you a less cluttered syntax for using strings as named fields.
There are a lot of strings keys this won't work for:
t["hello_world"] => t.hello_world -- works
t["hello world"] => t.hello world -- oops, space in the string
t["5 * 3"] => t.5 * 3 -- oops
t['[10]'] => t.[10] -- oops
Basically it only works if the string key would be a valid identifier.
Again, tables are indexed via [], and in most cases you need to use them:
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
["foo"] = 123, -- string key, number value
}
Only if you're using a string key which would work as a valid identifier (no spaces, contains only word characters, numbers, or underlines, and doesn't begin with a number) can you use the shortcut syntax. For the table above, that would be only 'foo':
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
foo = 123, -- string key, number value
}

Resources