How to get hash from array of hashes using a find? - ruby

I have a hash set in my code that declares an elegibility scale:
eligibility_scale = [{family_size: 2, minimum_income: 20161, maximum_income: 38200},
{family_size: 3, minimum_income: 25393, maximum_income: 43000},
{family_size: 4, minimum_income: 30613, maximum_income: 47750},
{family_size: 5, minimum_income: 35845, maximum_income: 51600},
{family_size: 6, minimum_income: 41065, maximum_income: 55400},
{family_size: 7, minimum_income: 46297, maximum_income: 59250},
{family_size: 8, minimum_income: 51517, maximum_income: 63050}]
I'm trying to get the hash result using the family_size as the search parameter.
income_bracket = eligibility_scale.select{|h| h["family_size"] == 4 }
# Expecting: {family_size: 4, minimum_income: 30613, maximum_income: 47750}
After running this code I'm getting an empty array.
Any suggestions on what I'm doing wrong?

Hash keys in the question are symbols, not strings.
You need to specify the key as symbol:
Replace following:
h["family_size"]
with:
h[:family_size]

Using select will return an array, first of all, so if your family_size is unique, you can just use find. Otherwise, use select in the same way, but expect to have an array of hashes returned.
Second of all, your hashes are using symbols, not string. Ideally, you're looking at writing something like this:
eligibility_scale.find { |i| i[:family_size] == 4 }
# => {family_size: 4, minimum_income: 30613, maximum_income: 47750}
This is assuming your family size is unique.

You've defined your hash using the key: value syntax which is shorthand for :key => value - meaning the keys are symbols and not strings
eligibility_scale.select {|h| h[:family_size] == 4 }

Related

Laravel collection->diff() not working when using select

I have table where I want to find difference in certain columns. I'm doing it with diff():
$inventoryitems1 = InventoryItem::where('inventory_id', $request->get('inventory1'))
->select('owner_id', 'location_id', 'asset_id')
->get();
$inventoryitems2 = InventoryItem::where('inventory_id', $request->get('inventory2'))
->select('owner_id', 'location_id', 'asset_id')
->get();
$difference = $inventoryitems2->diff($inventoryitems1);
And then i get empty array. But if I don't have select in my collection. It work, it shows all different rows. Is there anyother way to do this or this one is right but I'm not doing it the right way?
UPDATE
I have $inventoryitems1 collection that looks like this:
0: {asset_id: 2, owner_id: 2, location_id: 1}
1: {asset_id: 3, owner_id: 2, location_id: 1}
and $inventoryitems1 collection that looks like this:
0: {asset_id: 2, owner_id: 2, location_id: 1}
1: {asset_id: 3, owner_id: 6, location_id: 1}
I'm trying to find differences in those two collections, where we can see that owner_id is different in second collection. How can I only get those objects where there was some change (difference).

JSON is object instead of array, if array_diff returns assoc array on Collection->toArray()

My issue is in my json I am expecting an array, but am getting an object.
Details:
I have an array of numbers:
$numbers = [1];
I select from relationship, the "drawn numbers":
$drawnNumbers = Ball::whereIn('number', $numbers)->where('game_id', $card->game->id)->get()->map(function($ball) {
return $ball->number;
})->toArray();
I do a ->toArray() here. I want to find the numbers in $numbers that do not occur in $drawnNumbers. I do so like this:
$numbersNotYetDrawn = array_diff($numbers, $drawnNumbers);
My method then return $numbersNotYetDrawn (my headers accept is application/json).
So now the issue. When $drawnNumbers is an empty array, then the printed json is a regular array like this:
[
1
]
However if the relationship returns $drawnNumbers to be an array with numbers, then json is printed as an object:
{
"0" => 1
}
Does anyone know why this is? Anyway to ensure that json is array?
Edit:
Here is my actual data:
$drawnNumbers = Ball::whereIn('number', $numbers)->where('game_id', $card->game->id)->get()->map(function($ball) {
return $ball->number;
})->toArray();
$undrawnNumbers = array_diff($numbers, $drawnNumbers);
// $undrawnNumbers = array_values(array_diff($numbers, $drawnNumbers)); // temp fix
Replace
$numbersNotYetDrawn = array_diff($numbers, $drawnNumbers);
with
$numbersNotYetDrawn = array_values(array_diff($numbers, $drawnNumbers));
to make sure element keys are reset and array is treated as a simple list and serialized to a JSON list - instead of being treated as an associative array and serialized to a JSON object.
I recently had this same problem and wondered the same thing.
I solved it by adding "array_values", but I was wondering how to reproduce it.
I found it that it is reproduced when array_diff removes an element from the array that isn't the last element. So:
>>> $x
=> [
1,
2,
3,
4,
5,
]
>>> array_diff($x, [5]);
=> [
1,
2,
3,
4,
]
>>> array_diff($x, [1]);
=> [
1 => 2,
2 => 3,
3 => 4,
4 => 5,
]

How to return an array instead of a collection in Laravel?

In Laravel is it possible to select only one field and return that as a set/ array.
For example consider the model Foo which is linked to table foos which has field id, a, b, c.
Consider the following sample data:
(1, 10, 15, 20)
(1, 12, 15, 27)
(1, 17, 15, 27)
(1, 25, 16, 29)
(1, 28, 16, 40)
Now if I wanted to create a query that returns all the values of a where b is 15, I could do that like so:
Foo::select('a')->where('b', 15)->get();
However this will return an eloquent collection.
Instead how can I return instead an array like this:
[10, 12, 17]
Just use pluck() and ->toArray():
Foo::where('b', 15)->pluck('a')->toArray();
Laravel's pluck() method.
Laravel's toArray() method.
Do
Foo::where('b', 15)->lists('a')->all();
This will give you an array of ids. eg [2, 3, 5]
The lists method is deprecated and pluck need some parameter so, if you want to get all the attributed in array format, use it this way.
Foo::select('a')->where('b', 15)->get()->all();

Insert information from hash into iteration

I am trying to insert information from a hash monthly_multipliers into an iterator.
month_multipliers = { april: 1, may: 2, june: 3, july: 4, august: 5, september: 6, october: 7, november: 8, december: 9, january: 10, february: 11, march: 12}
months = ['april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december', 'january', 'february', 'march']
I then iterate through each month, and need to inject the monthly multiplier for each month, so june would be 3 august 5 etc.
months.each do |month|
instance_variable_set :"##{month}_income", (monthly_new_account_income * month_multipliers[month]) + previous_years_monthly_income
end
This bit doesn't work
month_multipliers[month])
I tried sending and getting an instance variable, but cannot get the format right.
month_multipliers has keys in Symbol objects, but months has keys as String objects. Use either all Symbol or String objects or convert keys to the correct object before retrieving the values from the hash.
This worked
#month_multipliers[month.to_sym]
I see your issue, youre using symbolic keys with string values. you can directly iterate over the month_multiplier for simplicity
month_multipliers.each_pair do |month, multiplier|
instance_variable_set :"##{month}_income", (monthly_new_account_income * multiplier) + previous_years_monthly_income
end

ActiveRecord query

I have two models Project and UrlList. A project :has_many url_list and a url_list :belongs_to project.
Now I have array for project id's all_projects = [1,2,5,8,16]. I want to retrieve all the records from url_list where project_id is one of those from all_projects array. How do I write code for it?
You can pass an array as value for an attribute to where method:
all_projects = [1, 2, 5, 8, 16]
url_lists = UrlList.where(:project_id => all_projects)
It'll generate SQL query like that:
SELECT `url_lists`.* FROM `url_lists` WHERE `project_id`.`user_id` IN (1, 2, 5, 8, 16)

Resources