I have a set of nested hashes. I would like to add the string "Assembly" to the array value associated with [:dennis_ritche][:languages]
def adding_to_dennis
programmer_hash =
{
:grace_hopper => {
:known_for => "COBOL",
:languages => ["COBOL", "FORTRAN"]
},
:alan_kay => {
:known_for => "Object Orientation",
:languages => ["Smalltalk", "LISP"]
},
:dennis_ritchie => {
:known_for => "Unix",
:languages => ["C"]
}
}
programmer_hash[:dennis_ritchie][:languages] << "Assembly"
end
This is the error I get no implicit conversion of Symbol into Integer"
I think the problem you're seeing is you're manipulating the hash inside the method and as a result are inadvertently returning the wrong thing. This method returns an Array because that's the last operation performed (<< on Array return the modified Array).
To fix it define a method that does the manipulation:
def add_to_hash(hash, programmer = :dennis_ritchie, language = 'Assembly')
hash[programmer][:languages] << language
end
Make that independent of the definition:
programmer_hash =
{
:grace_hopper => {
:known_for => "COBOL",
:languages => ["COBOL", "FORTRAN"]
},
:alan_kay => {
:known_for => "Object Orientation",
:languages => ["Smalltalk", "LISP"]
},
:margaret_hamilton => {
:known_for => "Apollo Program",
:languages => ["Assembly"]
},
:dennis_ritchie => {
:known_for => "Unix",
:languages => ["C"]
}
}
Then call it to manipulate the hash:
add_to_hash(programmer_hash)
The programmer_hash structure is then updated.
Related
So I have following array of hash:
my_array = [
{
"date" => "2022-12-01",
"pic" => "Jason",
"guard" => "Steven",
"front_desk" => "Emily"
},
{
"date" => "2022-12-02",
"pic" => "Gilbert",
"guard" => "Johnny",
"front_desk" => "Bella"
},
{
"date" => "2022-12-03",
"pic" => "Steven",
"guard" => "Gilbert",
"front_desk" => "Esmeralda"
}
]
My question is how do I change the structure of my array (grouping) by date in Ruby (Rails 7). Or in other word, I want to change my array into something like this:
my_array = [
{
"2022-12-01" => {
"pic" => "Jason",
"guard" => "Steven",
"front_desk" => "Emily"
{
},
{
"2022-12-02" => {
"pic" => "Gilbert",
"guard" => "Johnny",
"front_desk" => "Bella"
}
},
{
"2022-12-03" => {
"pic" => "Steven",
"guard" => "Gilbert",
"front_desk" => "Esmeralda"
}
}
]
Anyway, thanks in advance for the answer
I have tried using group_by method to group by its date, but it doesn't give the output I wanted
I've tried this method:
my_array.group_by { |element| element["date"] }.values
If you simply want a 1:1 mapping of your input objects to an output object of a new shape, then you just need to use Array#map:
my_array.map {|entry| {entry["date"] => entry.except("date")} }
(Hash#except comes from ActiveSupport, and is not standard Ruby, but since you're in Rails it should work just fine).
Both solutions assume the key "date" will be unique. If we cannot make this assumption safely, then each date should be mapped to an array of hashes.
my_array.each_with_object({}) do |x, hsh|
date = x["date"]
hsh[date] ||= []
hsh[date] << x.except("date")
end
Result:
{
"2022-12-01" => [
{"pic"=>"Jason", "guard"=>"Steven", "front_desk"=>"Emily"}
],
"2022-12-02" => [
{"pic"=>"Gilbert", "guard"=>"Johnny", "front_desk"=>"Bella"}
],
"2022-12-03" => [
{"pic"=>"Steven", "guard"=>"Gilbert", "front_desk"=>"Esmeralda"}
]
}
Or you may like:
my_array
.sort_by { |x| x["date"] }
.group_by { |x| x["date"] }
.transform_values { |x| x.except("date") }
Tried this, but couldn't get the desired output. I want to find documents without an array or a array smaller than 4.
db.collection.find({
'text' => { '$exists' => true },
'tags' => {
'$or' => [
{ '$exists' => false },
{ '$lt' => ['$size', 4] }
]
}
})
Error is:
unknown operator: $or
The $or operator should be at the top level, with an array of complete predicates:
db.collection.find({
'text' => { '$exists' => true },
'$or' => [
{'tags' => { '$exists' => false },
{'tags' => { '$lt' => ['$size', 4] }
]
})
I have an array of hashes:
{hashed_data = [
{:name => "frontend", :session_total => 145, :byte => 54667},
{:name => "backend_stagging", :session_total => 546, :byte => 895747},
{:name => "backend", :session_total => 5468, :byte => 8957447},
{:name => "frontend", :session_total => 54, :byte => 67387}
]
I must create the following hash. It does not have to be sorted.
hashed_data_modify = {
:frontend => {
:name => "frontend",
:summary => {:session_total => 546, :byte => 54667}
:backend => {
:name => "backend",
:details => {:session_total => 5468, :byte => 8957447},
:summary => { :name => "backend_stagging", :session_total => 546, :byte => 895747 }
}
that is, create a new key: frontend where hashed_data[:name] == "frontend" and create a key: backend where hashed_data[:name] == "backend". The frontend key contains only the data for the frontend data and for the backend only the backend.
I tried my sorting_method, it is bad:
hashed_data.select do |h|
if (h[:name] == "frontend") then
return hash = {
:frontend => {
:name => hashed_data[:name],
:details => [:session_total => hashed_data[:stot], :byte_in => hashed_data[:bin]]
}
} # :name => "frontend" etc.
(h[:name == "backend")
return hash = {
:backend => {:name => hashed_data[:name] #:name => "backend"}
} etc.
end
end
Please help.
I'm guessing this is what you want.
hashed_data.group_by { |h| h[:name] }.
map { |_,v| v.max_by { |g| g[:session_total] } }
#=> [{:name=>"frontend", :session_total=>145, :byte=>54667},
# {:name=>"backend_stagging", :session_total=>546, :byte=>895747},
# {:name=>"backend", :session_total=>5468, :byte=>8957447}]
Note that the first calculation is the following.
hashed_data.group_by { |h| h[:name] }
#=> {"frontend"=>[{:name=>"frontend", :session_total=>145, :byte=>54667},
# {:name=>"frontend", :session_total=>54, :byte=>67387}],
# "backend_stagging"=>[{:name=>"backend_stagging", :session_total=>546,
# :byte=>895747}],
# "backend"=>[{:name=>"backend", :session_total=>5468, :byte=>8957447}]}
Firstly, you say you want the first element of the array returned to be:
{:name=>"frontend", :session_total=>546, :byte=>54667}
I'm guessing the value of :session_total is a typo, and should be 145.
Secondly, I assume when two or more hashes have the same value of :name (here just "frontend"), you want to keep the one for which the value session_total is greatest (but that's a truly wild guess).
Thirdly, you seem to want to change the value "backend_staging" to the key :summary. If so, that's not central to the question and just a nuisance for those giving answers, so I've disregarded that requirement.
I have recursively put together an array of hashes for perl, which looks something like this :
[
{
'Default' => {
'Elect' => { 'P' => 1 }
}
},
{
'Default' => {
'Elect' => { 'A' => 1 }
}
},
{
'Default' => {
'Elect' => { 'M' => 1 }
}
},
{
'Default' => {
'Elect' => { 'I' => 1 }
}
},
{
'Default' => {
'Picker' => { 'L' => 1 }
}
},
]
My aim is to make this more condensed and look like a single hash, as compared to array of hashes. Is there anyway in which i can make this array of hashes look like a hash:
{
'Default' =>{
'Elect' =>{
'P' => 1,
'A' => 1,
'M' => 1,
'I' => 1,
},
'Picker' => {
'L' => 1
}
}
}
Well, here is a simple recursive procedure to merge two hash references:
sub merge {
my ($xs, $ys) = #_;
while (my ($k, $v) = each %$ys) {
if ('HASH' eq ref $v) {
merge($xs->{$k} //= {}, $v);
}
else {
$xs->{$k} = $v;
}
}
}
Then:
my $data = ...; # your input data structure
my $acc = {};
merge($acc, $_) for #$data;
which produces the result you desire in $acc.
There is also the Hash::Merge module, with that:
use Hash::Merge 'merge';
my $acc = {};
$acc = merge $acc, $_ for #$data;
I have the following hashref of hashrefs structure:
$hashref = {
user1 => {
key1 => "unique_value1",
...
key99 => "value1_99"
},
...
user26 => {
key1 => "unique_value2",
...
key99 => "value1_99"
},
user99 => {
key1 => "unique_value1",
...
key99 => "value99_99"
},
};
What I want out:
$hashref = {
"unique_value1" => ["user1","user99"],
"unique_value2" => ["user26"]
};
I've historically built the inverted map on create, but I'm getting lazy.
Any one line sugar I could use for this?
Thank you.
One way:
my $h;
push (#{$h->{$hashref->{$_}{key1}}}, $_) for keys %$hashref;
my %users_by_uval;
for my $user_id (%$users) {
push #{ $users_by_uval{ $users->{$user_id}{key1} } }, $user_id;
}