Related
I have obtained the set of odd nodes of a graph and generated all its subsets. Now I want to separate those subsets whose size is odd.
I would appreciate it if you could help me :)
There are two solutions in my mind, the first one works correctly, but I have to add a null collection. And the second solution, I don't know how to write it correctly
range SS=1..ftoi(2^n_odd-1);
{int} Sub_odd[s in SS] = {item(odd_nodes,i-1) | i in 1..n_odd : (s div ftoi(2^(i-1))) mod 2 == 1};
{int} Sub_odd_odd[s in SS] = card(Sub_odd[s]) mod 2 ==1? Sub_odd[s]:{} ;
{int} Sub_odd_odd = union(Sub_odd[s] | s in SS : card(Sub_odd[s]) mod 2 ==1 );
If you consider the powerset example you can filter and keep the odd instances:
{string} s={"A","B","C","D"};
range r=1.. ftoi(pow(2,card(s)));
{string} s2 [k in r] = {i | i in s: ((k div (ftoi(pow(2,(ord(s,i))))) mod 2) == 1)};
{int} subr={i| i in r:card(s2[i]) mod 2==1};
{string} subs2[i in subr]=s2[i];
execute
{
writeln(s2);
writeln(subs2);
}
which gives
[{"A"} {"B"} {"A" "B"} {"C"} {"A" "C"} {"B" "C"} {"A" "B" "C"} {"D"} {"A" "D"}
{"B" "D"} {"A" "B" "D"} {"C" "D"} {"A" "C" "D"} {"B" "C" "D"} {"A"
"B" "C" "D"} {}]
[{"A"} {"B"} {"C"} {"A" "B" "C"} {"D"} {"A" "B" "D"} {"A" "C" "D"} {"B" "C"
"D"}]
I have a hash of the following form:
{ 1 => [], 2 => ["A", "B"], 3 => ["C"], 4 => ["B", "C"], 5 => ["D"] }
what's the best way to transform this in Ruby to:
{ "A" => [2], "B" => [2, 4], "C" => [3, 4], "D" => [5], "default" => [1] }
The best way I know.
hash = { 1 => [], 2 => ['A','B'], 3 => ['C'], 4 => ['B','C'], 5 => ['D'] }
new_hash = hash.inject({}) do |result, (key, values)|
values.each do |value|
result[value] ||= []
result[value].push(key)
end
result[:default] = [key] if values.empty?
result
end
puts new_hash
A bit of more functional approach:
array
.flat_map {|k,v| v.product([k])}
.group_by(&:first)
.transform_values {|v| v.map(&:last) }
input = { 1 => [], 2 => ['A', 'B'], 3 => ['C'], 4 => ['B', 'C'], 5 => ['D'], 6 => [] }
output =
input.each_with_object(Hash.new([])) do |(key, values), hash|
values.each { |value| hash[value] += [key] }
hash['default'] += [key] if values.empty?
end
output
# => {"default"=>[1, 6], "A"=>[2], "B"=>[2, 4], "C"=>[3, 4], "D"=>[5]}
I have an array of hashes as follows:
details = [
{:name => "Alice", :age => 20},
{:name => "Ted", :age => 25},
{:name => "Poppy", :age => 33},
{:name => "Amy", :age => 20},
{:name => "Ted", :age => 90},
{:name => "Amy", :age => 22},
{:name => "Ted", :age => 23}
]
I want to be able to sort so that I can order based on how many times the names of each person appear. For example, output might be:
"Ted, Ted, Ted, Amy, Amy, Alice, Poppy"
Can anyone please help? :)
Thanks
Get a name-counting hash, then sort by the name counts:
details.each.with_object(Hash.new(0)) { |e, c| c[e[:name]] += 1 }.
then { |c| details.sort_by { |e| -c[e[:name]] } }.
map { |e| e[:name] }
this will return based on the name attribute occurrence:
sorted_group_details = details.group_by{|d| d[:name]}.sort_by{|key, val| val.count}
by default, it returns ascending order. if you want to order by the most occurrence just add reverse
sorted_group_details.reverse
and, if you want to return a flatten object from the grouped array:
sorted_group_details.map{|d| d[1]}.flatten
output_array = []
Hash[details.group_by{|data| data[:name]}.transform_values(&:count).sort_by{|k,v| v}.reverse].each{|key,value| value.times do output_array.push(key) end }
output_array will have the results
details.map { |h| h[:name] }.
group_by(&:itself).
values.
sort_by { |a| -a.size }.
flatten
#=> ["Ted", "Ted", "Ted", "Amy", "Amy", "Alice", "Poppy"]
One can tack on .join(', ') if a string is desired instead:
"Ted, Ted, Ted, Amy, Amy, Alice, Poppy"
The most expensive operation here is sorting, which is O(n*log(n)); all other operations are O(n). Let
arr = ["Alice", "Ted", "Poppy", "Amy", "Ted", "Amy", "Ted"]
By executing group_by and values before sort_by, only
n = arr.uniq.size
#=> 4
values need be sorted, as opposed to sorting all 7 elements arr.
The steps are as follows.
b = details.map { |h| h[:name] }
#=> ["Alice", "Ted", "Poppy", "Amy", "Ted", "Amy", "Ted"]
c = b.group_by(&:itself)
#=> {"Alice"=>["Alice"], "Ted"=>["Ted", "Ted", "Ted"], "Poppy"=>["Poppy"],
# "Amy"=>["Amy", "Amy"]}
d = c.values
#=> [["Alice"], ["Ted", "Ted", "Ted"], ["Poppy"], ["Amy", "Amy"]]
e = d.sort_by { |a| -a.size }
#=> [["Ted", "Ted", "Ted"], ["Amy", "Amy"], ["Alice"], ["Poppy"]]
e.flatten
#=> ["Ted", "Ted", "Ted", "Amy", "Amy", "Alice", "Poppy"]
I'm new in Ruby. I have two arrays of hashes
arr1 = [{"one"=> {"1"=> "a", "2" => "b"}, "two" => {"3" => "n", "5" => "h", "7" => "k"}]
arr2 = [{"one"=> {"8"=> "f", "11" => "r"}, "two" => {"7" => "o", "6" => "b", "14" => "b"}]
and I want to have one array like this:
arr3 = [{
"one"=> {"1"=> "a", "2" => "b", "8"=> "f", "11" => "r"},
"two" => {3" => 'n", "5" => "h", "7" => "k", 7" => 'o", "6" => "b", "14" => "b"}
]
so I want to merge hashes by keys and "add" their values. Can anyone help?
arr1 = [{"one"=>{"1"=>"a", "2"=>"b"}, "two"=>{"3"=>"n", "5"=>"h", "7"=>"k"}}]
arr2 = [{"one"=>{"8"=>"f", "11"=>"r"}, "two"=>{"7"=>"o", "6"=>"b", "14"=>"b"}}]
(arr1+arr2).each_with_object({}) { |g,h| h.update(g) { |_,o,n| o.merge(n) } }
# => {"one"=>{"1"=>"a", "2"=>"b", "8"=>"f", "11"=>"r"},
# "two"=>{"3"=>"n", "5"=>"h", "7"=>"o", "6"=>"b", "14"=>"b"}}
This uses the form of Hash#update (aka merge!) that uses a block ({ |_k,o,n| o.merge(n) }) to determine the value of the key _k when both hashes being merged have that key. (_ in _k tells the reader that that block variable is not used in the block calculation.) o and n are the values of that key in h and g respectively.
For each key k equal to "one" or "two", if the values (hashes) of arr1.first[k] and arr2.first[k] have a common key l, the merge operation will cause the value of l in arr1 will be overwritten by the value of l in arr2. If, for example, arr1.first["one"] #=> {"1"=>"a", "2"=>"b"} and arr2.first["one"] #=> {"8"=>"f", "2"=>"r"}, the merge will return {"1"=>"a", "2"=>"r", "8"=>"f"}
Even though arr1 and arr2 each contain a single element (a hash), the code above works fine when the arrays contain multiple hashes, and when there are more than two arrays. If the arrays always contain a single hash, the arrays serve no purpose and we might instead just reference the hashes:
h1 = {"one"=>{"1"=>"a", "2"=>"b"}, "two"=>{"3"=>"n", "5"=>"h", "7"=>"k"}}
h2 = {"one"=>{"8"=>"f", "11"=>"r"}, "two"=>{"7"=>"o", "6"=>"b", "14"=>"b"}}
and replace arr1+arr2 with [h1+h2].
Maybe not the most elegant but this works:
arr1 = [{"one"=>{"1"=>"a", "2"=>"b"}, "two"=>{"3"=>"n", "5"=>"h", "7"=>"k"}}]
arr2 = [{"one"=>{"8"=>"f", "11"=>"r"}, "two"=>{"7"=>"o", "6"=>"b", "14"=>"b"}}]
arr3 = []
arr1[0].each_key{|k| arr3<< {k => arr1[0][k].merge(arr2[0][k])}}
arr3
If you don't know how many hashes your original array will contain, simply replace arr1[0].each_key with arr1.each_index{|i| arr1[i].each_key and replace 0 with i in the merge.
I have some key-value pair strings in an array:
array = [ "Name = abc", "Id = 123", "Interest = Rock Climbing" ]
I need to convert it to a hash:
hash = { "Name" => "abc", "Id" => "123", "Interest" => "Rock Climbing" }
I must be doing something wrong because I'm getting weird mappings with my .shift.split resulting in {"Name=abc"=>"Id=123"}.
All you need to do is split each part of the array into a key and value (yielding an array of two-element arrays) and then pass the result to the handy Hash[] method:
arr = [ "Name = abc", "Id = 123", "Interest = Rock Climbing" ]
keys_values = arr.map {|item| item.split /\s*=\s*/ }
# => [ [ "Name", "abc" ],
# [ "Id", "123" ],
# [ "Interest", "Rock Climbing" ] ]
hsh = Hash[keys_values]
# => { "Name" => "abc",
# "Id" => "123",
# "Interest" => "Rock Climbing" }
You can do it this way (using Enumerable#each_with_object):
array.each_with_object({}) do |a, hash|
key,value = a.split(/\s*=\s*/) # splitting the array items into key and value
hash[key] = value # storing key => value pairs in the hash
end
# => {"Name"=>"abc", "Id"=>"123", "Interest"=>"Rock Climbing"}
If you find it little difficult to understand the each_with_object, you can do it in a naive way (Just accumulating the key and values in the result_hash):
result_hash = {}
array.each do |a|
key,value = a.split(/\s*=\s*/) # splitting the array items into key and value
result_hash[key] = value # storing key => value pairs in the result_hash
end
result_hash
# => {"Name"=>"abc", "Id"=>"123", "Interest"=>"Rock Climbing"}
Try this
array.map {|s| s.split('=')}.to_h
=> {"Name "=>" abc", "Id "=>" 123", "Interest "=>" Rock Climbing"}
array.each_with_object({}) { |s,h| h.update([s.split(/\s*=\s*/)].to_h) }
#=> {"Name"=>"abc", "Id"=>"123", "Interest"=>"Rock Climbing"}
For Ruby versions prior to 2.0 (when Array#to_h was introduced) replace [s.split(/\s*=\s*/)].h with Hash[[s.split(/\s*=\s*/)]].
The steps:
enum = array.each_with_object({})
#=> #<Enumerator: ["Name = abc", "Id = 123",
# "Interest = Rock Climbing"]:each_with_object({})>
We can see the elements of this enumerator by converting it to an array:
enum.to_a
#=> [["Name = abc", {}], ["Id = 123", {}], ["Interest = Rock Climbing", {}]]
The first element of enum is passed to the block, the block variables are assigned:
s,h = enum.next
#=> ["Name = abc", {}]
s #=> "Name = abc"
h #=> {}
and the block calculation is performed:
h.update([s.split(/\s*=\s*/)].to_h)
#=> h.update([["Name", "abc"]].to_h)
# {}.update({"Name"=>"abc"})
# {"Name"=>"abc"}
which is the updated value of h.
The next element of enum passed to the block is:
s,h = enum.next
#=> ["Id = 123", {"Name"=>"abc"}]
s #=> "Id = 123"
h #=> {"Name"=>"abc"}
h.update([s.split(/\s*=\s*/)].to_h)
#=> {"Name"=>"abc", "Id"=>"123"}
and so on.