I'm trying to check if a value of an attribute is included in an array.
Like that:
#teste = []
#vacancies_interns.each do |vacancy_intern|
#teste << vacancy_intern.id
end
#hr_curriculum_interns = HrCurriculumIntern.where(#teste.include?(:id) == true)
The output of the variable #teste, as an example, is:
[5, 6, 8, 10, 12, 15]
I am listing the variable # hr_curriculum_interns on a table, and even with the condition, is listing all table rows.
Sorry for English :P
It as simple as:
#hr_curriculum_interns = HrCurriculumIntern.where(id: #teste)
Related
I'm trying to add support for multiple groups in my vehicles API. Currently we only support grouping by a single column like this.
Vehicle.group(:fuel_type).count
Which gives me a result like this:
{
"Petrol": 78,
"Diesel": 22
}
When I add multiple groups like this:
Vehicle.group(:fuel_type, :registration_status).count
I get the following result, which isn't as pretty in an API response. Also it's missing the combination Petrol and Exported since the count is 0.
{
"['Diesel', 'Scrapped']": 5,
"['Petrol', 'Registered']": 6,
"['Petrol', 'Scrapped']": 30,
"['Diesel', 'Registered']": 1,
"['Diesel', 'Deregistered']": 11,
"['Petrol', 'Deregistered']": 42,
"['Diesel', 'Exported']": 5
}
I would like it to be formatted like this instead:
{
"Diesel": {
"Scrapped": 5,
"Registered": 1,
"Deregistered": 11,
"Exported": 5
},
"Petrol": {
"Scrapped": 30,
"Registered": 6,
"Deregistered": 42,
"Exported: 0
}
}
Ideally I would like to support n nested groups, where every combination is displayed in every layer eg. even though there are no exported petrol cars, then it should still be included in the response with a count of 0.
I actually posted my question to openAI's ChatGPT and got a working implementation. Here is the snippet incase anyone has a similar issue:
def handle_hash(query)
return query unless query.is_a?(Hash)
result = {}
query.each do |key, value|
if key.is_a?(String)
result[key] = value
else
current = result
key[0...-1].each do |element|
current[element] ||= {}
current = current[element]
end
current[key[-1]] = value
end
end
result
end
a little help with getting data out of a string.
Assuming I executed a sql query and now have a string(which set as hash on db):
"{\"users_associated\":{\"User:4\":6,\"User:22\":28,\"User:30\":36}}"
(Which stands for User:ID : User.display_id)
How can I get a substring the includes all users ids or all their display ids, so I'll have something like 4,22,30 or 6,22,36)?
Thanks!
It's common for data systems to return data in a serialized form, i.e. using data types that facilitate transmission of data. One of these serializable data types is String, which is how your JSON data object has been received.
The first step would be to de-serialize (or parse) this String into a Hash object using JSON.parse and tease out just the data value for key "users_associated".
your_string = "{\"users_associated\":{\"User:4\":6,\"User:22\":28,\"User:30\":36}}"
hash = JSON.parse(your_string)
data = hash["users_associated"]
#=> {"User:4":6, "User:22": 28, "User:30": 36}
Hash#keys gives you an array of a hash's keys.
Hash#values gives you an array of a hash's data values.
keys = data.keys
#=> ["User:4", "User:22", "User:30"]
values = data.values
#=> [6, 28, 36]
Array#join lets you string together the contents of an array with a defined separator, , in this case.
display_ids = keys.join(',')
#=> "6,28,36"
For the User IDs, you could Array#map every element of the values array to replace every string occurrence of "User:" with "", using String#gsub.
user_ids = values.map{|user_id| user_id.gsub("User:", "")}
#=> ["4", "22", "30"]
Then, in a similar way to display_ids, we can Array#join the contents of the user_ids array to a single string.
user_ids = user_ids.join(",")
#=> "4,22,30"
You can create two helper methods. I'm leaving return values as arrays because I assume you would need to iterate on them at some point and also converting the user id's to integers.
def extract_display_ids(json)
json['users_associated'].values
end
def extract_user_ids(some_data)
json['users_associated'].keys.map{ |key| key.split(':').last.to_i }
end
some_data = JSON.parse("{\"users_associated\":{\"User:4\":6,\"User:22\":28,\"User:30\":36}}")
extract_display_ids(some_data)
#=> [6, 28, 36]
extract_user_ids(some_data)
#=> [4, 22, 30]
If possible though, I would recommend trying to get a better data format:
{ users_associated:
[{ user_id : 4, display_id:6 }, { user_id : 4, display_id:6 }]
}
I wrote class for this. If you want, you can add it to your project and use it as follows:
require 'json'
class UserSubstringExtractor
def initialize(user_json_data)
#user_json_data = user_json_data
end
def display_ids
user_data.dig('users_associated').values
end
def user_ids
user_data.dig('users_associated').keys.map { |u| u.split(':').last.to_i }
end
private
def user_data
JSON.parse(#user_json_data)
end
end
user_json_data = '{"users_associated":{"User:4":6,"User:22":28,"User:30":36}}'
extractor = UserSubstringExtractor.new(user_json_data)
p extractor.display_ids
#=> [6, 28, 36]
p extractor.user_ids
#=> [4, 22, 30]
In my Rails 5 app I have something like this:
a = [1,2,3]
a.map do |entry|
entry.delete if condition == true
end
This removes the entry if the condition is true.
Now I have this:
a = [[1,2],[2,3],[3,4]]
a.map do |entry|
entry.delete if condition == true
end
This loops through a but now entry is an array and delete should remove the entire entry but instead I get:
wrong number of arguments (given 0, expected 1)
Dos anybody know how I can loop through an array of arrays and remove an entire subarray?
Try this:
a.delete_if {condition}
For example:
a = [[1,2],[2,3],[3,4]]
a.delete_if {|entry| entry[0] == 1 }
# returns [[2, 3], [3, 4]]
instead of using map you should use flat_map see: https://apidock.com/ruby/Enumerable/flat_map
I have two tables connected with habtm relation (through a table).
Table1
id : integer
name: string
Table2
id : integer
name: string
Table3
id : integer
table1_id: integer
table2_id: integer
I need to group Table1 records by simmilar records from Table2. Example:
userx = Table1.create()
user1.table2_ids = 3, 14, 15
user2.table2_ids = 3, 14, 15, 16
user3.table2_ids = 3, 14, 16
user4.table2_ids = 2, 5, 7
user5.table2_ids = 3, 5
Result of grouping that I want is something like
=> [ [ [1,2], [3, 14, 15] ], [ [2,3], [3,14, 16] ], [ [ 1, 2, 3, 5], [3] ] ]
Where first array is an user ids second is table2_ids.
I there any possible SQL solution or I need to create some kind of algorithm ?
Updated:
Ok, I have a code that is working like I've said. Maybe someone who can help me will find it useful to understand my idea.
def self.compare
hash = {}
Table1.find_each do |table_record|
Table1.find_each do |another_table_record|
if table_record != another_table_record
results = table_record.table2_ids & another_table_record.table2_ids
hash["#{table_record.id}_#{another_table_record.id}"] = results if !results.empty?
end
end
end
#hash = hash.delete_if{|k,v| v.empty?}
hash.sort_by{|k,v| v.count}.to_h
end
But I can bet that you can imagine how long does it takes to show me an output. For my 500 Table1 records it's something near 1-2 minutes. If I will have more, time will be increased in progression, so I need some elegant solution or SQL query.
Table1.find_each do |table_record|
Table1.find_each do |another_table_record|
...
Above codes have performance issue that you have to query database N*N times, which could be optimized down to one single query.
# Query table3, constructing the data useful to us
# { table1_id: [table2_ids], ... }
records = Table3.all.group_by { |t| t.table1_id }.map { |t1_id, t3_records|
[t1_id, t3_records.map(&:table2_id)]
}.to_h
Then you could do exactly the same thing to records to get the final result hash.
UPDATE:
#AKovtunov You miss understood me. My code is the first step. With records, which have {t1_id: t2_ids} hash, you could do sth like this:
hash = {}
records.each do |t1_id, t2_ids|
records.each do |tt1_id, tt2_ids|
if t1_id != tt1_id
inter = t2_ids & tt2_ids
hash["#{t1_id}_#{tt1_id}"] = inter if !inter.empty?
end
end
end
Working with the following code, I need to return only records where the `point' attribute is unique. I can't seem to get there by myself.
uniques = Item.find_all_by_item_id(item_id)
uniques.sort! {|a, b| b.point <=> a.point } # how do I reject the equal points?
In other words.. I guess, how do you make [0, 1, 1, 1, 2, 3, 3, 4, 4, 7] #=> [0, 2, 7] ?
How about this:
# Get the number of items with each point value
counts = Item.count("point", :group => "point")
# Get the IDs of all entries that only show up once
unique_ids = counts.collect { |count| count[0] if count[1] == 1 }.compact
unique_items = Item.find_all_by_id(unique_ids)
I can think of few ways off the top of my head to do this:
uniques.reject!{|u| uniques.select{|x| x == u}.size > 1}
Basically iterate through the uniques array and then see if there is more than one of those items in the array. Obviously there are lots of clever ways to speed this up, but for small arrays this should work.
or
h = Hash.new(0)
uniques.each{|u| h[u] += 1}
h.reject{|k,v| v > 1}.keys
Basically count how many times each item shows up in a hash, if its more than one reject it and then just look at the keys.