{"offer:manage_all"=>["0", "1"], "offer:index"=>["0"], "offer:new"=>["0"], "offer:show"=>["0"], "offer:create"=>["0"], "offer:update"=>["0"], "offer:destroy"=>["0"], "job:manage_all"=>["0", "1"], "job:index"=>["0", "1"], "job:new"=>["0"], "job:create"=>["0"], "job:edit"=>["0"], "job:update"=>["0"], "job:destroy"=>["0"], "user:manage_all"=>["0", "1"], "user:index"=>["0"], "user:new"=>["0"], "user:create"=>["0"], "user:edit"=>["0"], "user:update"=>["0"], "user:destroy"=>["0"], "account_access:manage_all"=>["0", "1"], "role:manage_all"=>["0", "1"], "role:index"=>["0"], "role:new"=>["0"], "role:create"=>["0"], "role:edit"=>["0"], "role:update"=>["0"], "role:destroy"=>["0"], "welcome_package:manage_all"=>["0", "1"]}
I need to convert this hash into a string.
If the key has a value of 1 the key needs to be pushed to a an array.
The above will has will need to equal this because they are the keys with a value that includes 1.
["offer:manage_all", "job:manage_all", "job:index", "account_access:manage_all", "role:manage_all", "welcome_package:manage_all"]
Thank you in advance.
Given the hash:
h = {"cat"=>["0", "1"], "dog"=>["0"], "pig"=>["0", "1"], "owl"=>["0"], "hen"=>["0", "1"] }
I would write
h.keys.select { |k| h[k].include? "1" }
#=> ["cat", "pig", "hen"]
try method select and keys
hash = {"offer:manage_all"=>["0", "1"], "offer:index"=>["0"], "offer:new"=>["0"], "offer:show"=>["0"], "offer:create"=>["0"], "offer:update"=>["0"], "offer:destroy"=>["0"], "job:manage_all"=>["0", "1"], "job:index"=>["0", "1"], "job:new"=>["0"], "job:create"=>["0"], "job:edit"=>["0"], "job:update"=>["0"], "job:destroy"=>["0"], "user:manage_all"=>["0", "1"], "user:index"=>["0"], "user:new"=>["0"], "user:create"=>["0"], "user:edit"=>["0"], "user:update"=>["0"], "user:destroy"=>["0"], "account_access:manage_all"=>["0", "1"], "role:manage_all"=>["0", "1"], "role:index"=>["0"], "role:new"=>["0"], "role:create"=>["0"], "role:edit"=>["0"], "role:update"=>["0"], "role:destroy"=>["0"], "welcome_package:manage_all"=>["0", "1"]}
keys = hash.select{ |key,val| val.include? "1" }.keys
#=> ["offer:manage_all", "job:manage_all", "job:index", "user:manage_all", "account_access:manage_all", "role:manage_all", "welcome_package:manage_all"]
Related
how from this:
[
["1", "className", "Connection"],
["2", "className", "Connection"],
["1", "connectorId", "100"],
["2", "connectorId", "100"],
["1", "part_1", "side_1"],
["2", "part_1", "side_1"],
["1", "part_2", "bottomPanel_1"],
["2", "part_2", "bottomPanel_1"],
["1", "transformation", nil],
["2", "transformation", nil]
]
resive something like this:
[
[["1", "className", "Connection"],
["1", "connectorId", "100"],
["1", "part_2", "bottomPanel_1"],
["1", "part_1", "side_1"],
["1", "transformation", nil]],
[["2", "part_1", "side_1"],
["2", "className", "Connection"],
["2", "connectorId", "100"],
["2", "part_2", "bottomPanel_1"],
["2", "transformation", nil]]
]
I need to group nested arrays by first element.
thanks in advance.
Give a your array, try this
a.group_by(&:first).values
=> [
[["1", "className", "Connection"],
["1", "connectorId", "100"],
["1", "part_1", "side_1"],
["1", "part_2", "bottomPanel_1"],
["1", "transformation", nil]],
[["2", "className", "Connection"],
["2", "connectorId", "100"],
["2", "part_1", "side_1"],
["2", "part_2", "bottomPanel_1"],
["2", "transformation", nil]]
]
Ruby's Enumerable module has all kinds of goodies built into it, and group_by does very close to what you want.
arr.group_by { |x| x[0] } # Assuming your input array is called arr
This results in a dictionary where the keys are the groupings (i.e. the first elements of the inner arrays) and the values are the lists of elements in that group. That is,
{
"1" => [
["1", "className", "Connection"],
["1", "connectorId", "100"],
["1", "part_1", "side_1"],
["1", "part_2", "bottomPanel_1"],
["1", "transformation", nil]
],
"2" => [
["2", "className", "Connection"],
["2", "connectorId", "100"],
["2", "part_1", "side_1"],
["2", "part_2", "bottomPanel_1"],
["2", "transformation", nil]
]
}
If all you want are the groupings, not the keys, then we can just do
arr.group_by { |x| x[0] }.values
which gives you exactly the result you want.
While the other answers are both correct, your end result still looks cumbersome to deal with. I would recommend taking this a step further so that the resulting object is easier to utilize
a =[
["1", "className", "Connection"],
["2", "className", "Connection"],
["1", "connectorId", "100"],
["2", "connectorId", "100"],
["1", "part_1", "side_1"],
["2", "part_1", "side_1"],
["1", "part_2", "bottomPanel_1"],
["2", "part_2", "bottomPanel_1"],
["1", "transformation", nil],
["2", "transformation", nil]
]
# shift will mutate the inner Arrays
# if this does not matter you can remove map(&:dup)
b = a.map(&:dup).group_by(&:shift).transform_values(&:to_h)
#=> {"1"=>{
# "className"=>"Connection",
# "connectorId"=>"100",
# "part_1"=>"side_1",
# "part_2"=>"bottomPanel_1",
# "transformation"=>nil},
# "2"=>{
# "className"=>"Connection",
# "connectorId"=>"100",
# "part_1"=>"side_1",
# "part_2"=>"bottomPanel_1",
# "transformation"=>nil}
# }
Now the resulting Object is a Hash which will make accessing the data much easier. e.g. to access 1's connectorId
Your Result: b[0][1][2] or b.dig(0,1,2)
Hash Result: b["1"]["connectorId"]
Turning the results into a Hash will also allow for order independence in the event that the order of a is not as determinate as it is in the post.
I have a set of array like this:
[["1","2"],["1","3"],["2","3"],["2","5"]]
I want to find the union of first values like
["1","2"],["1","3"] matches so i need to create new array like ["1","2,3"]
so the resulting array will be like
[["1","2,3"],["2","3,5"]]
Like most problems in Ruby, the Enumerable module does the job:
input = [["1","2"],["1","3"],["2","3"],["2","5"]]
result = input.group_by do |item|
# Group by first element
item[0]
end.collect do |key, items|
# Compose into new format
[
key,
items.collect do |item|
item[1]
end.join(',')
]
end
puts result.inspect
# => [["1", "2,3"], ["2", "3,5"]]
The group_by method comes in very handy when aggregating things like this, and collect is great for rewriting how the elements appear.
What you are asking for is not a true union for a true union of each 2 it would be:
data = [["1","2"],["1","3"],["2","3"],["2","5"]]
data.each_slice(2).map{|a,b| a | b.to_a }
#=> [["1","2","3"],["2","3","5"]]
Here is a very simple solution that modifies this concept to fit your needs:
data = [["1","2"],["1","3"],["2","3"],["2","5"]]
data.each_slice(2).map do |a,b|
unified = (a | b.to_a)
[unified.shift,unified.join(',')]
end
#=> [["1", "2,3"], ["2", "3,5"]]
Added to_a to piped variable b in the event that there are an uneven number of arrays. eg.
data = [["1","2"],["1","3"],["2","3"],["2","5"],["4","7"]]
data.each_slice(2).map do |a,b|
unified = (a | b.to_a)
[unified.shift,unified.join(',')]
end
#=> [["1", "2,3"], ["2", "3,5"], ["4","7"]]
If you meant that you want this to happen regardless of order then this will work but will destroy the data object
data.group_by(&:shift).map{|k,v| [k,v.flatten.join(',')]}
#=> [["1", "2,3"], ["2", "3,5"], ["4","7"]]
Non destructively you could call
data.map(&:dup).group_by(&:shift).map{|k,v| [k,v.flatten.join(',')]}
#=> [["1", "2,3"], ["2", "3,5"], ["4","7"]]
Here's another way.
Code
def doit(arr)
arr.each_with_object({}) { |(i,*rest),h| (h[i] ||= []).concat(rest) }
.map { |i,rest| [i, rest.join(',')] }
end
Examples
arr1 = [["1","2"],["1","3"],["2","3"],["2","5"]]
doit(arr1)
#=> [["1", "2,3"], ["2", "3,5"]]
arr2 = [["1","2","6"],["2","7"],["1","3"],["2","3","9","4","cat"]]
doit(arr2)
# => [["1", "2,6,3"], ["2", "7,3,9,4,cat"]]
Explanation
For arr1 above, we obtain:
enum = arr1.each_with_object({})
#=> #<Enumerator: [["1", "2"], ["1", "3"], ["2", "3"],
# ["2", "5"]]:each_with_object({})>
We can convert enum to an array see its elements:
enum.to_a
#=> [[["1", "2"], {}], [["1", "3"], {}],
# [["2", "3"], {}], [["2", "5"], {}]]
These elements will be passed into the block, and assigned to the block variables, by Enumerator#each, which will invoke Array#each. The first of these elements ([["1", "2"], {}]) can be obtained by invoking Enumerator#next on enum:
(i,*rest),h = enum.next
#=> [["1", "2"], {}]
i #=> "1"
rest #=> ["2"]
h #=> {}
We then execute:
(h[i] ||= []).concat(rest)
#=> (h["1"] ||= []).concat(["2"])
#=> (nil ||= []).concat(["2"])
#=> [].concat(["2"])
#=> ["2"]
each then passes the next element of enum to the block:
(i,*rest),h = enum.next
#=> [["1", "3"], {"1"=>["2"]}]
i #=> "1"
rest #=> ["3"]
h #=> {"1"=>["2"]}
(h[i] ||= []).concat(rest)
#=> (h["1"] ||= []).concat(["3"])
#=> (["2"] ||= []).concat(["3"])
#=> ["2"].concat(["3"])
#=> ["2", "3"]
After passing the last two elements of enum into the block, we obtain:
h=> {"1"=>["2", "3"], "2"=>["3", "5"]}
map creates an enumerator:
enum_h = h.each
#=> > #<Enumerator: {"1"=>["2", "3"]}:each>
and calls Enumerator#each (which calls Hash#each) to pass each element of enum_h into the block:
i, rest = enum_h.next
#=> ["1", ["2", "3"]]
then computes:
[i, rest.join(',')]
#=> ["1", ["2", "3"].join(',')]
#=> ["1", "2,3"]
The other element of enum_h is processed similarly.
For this program I'm making i need to join together some arrays in a multidimensional array:
What the array is:
[["2", "2"]["0", "9"]["2", "2"]["2", "7"]["1", "7"]["0", "8"]["0", "1"]
["0", "9"]]
And I want it to become like this:
["22", "09", "22", "27", "17", "08", "01", "09"]
Sorry if this is a really dumb question but if someone can help me I would be very happy, and if it is impossible to do this, then please tell me.
Thanks.
Try this:
multi_dimensional_array = [["2", "2"], ["0", "9"], ["2", "2"], ["2", "7"], ["1", "7"], ["0", "8"], ["0", "1"], ["0", "9"]]
multi_dimensional_array.map(&:join)
map iterates over the entries in your array and returns a copy of the array with modified entries.
&:join sends join to every member of the iteration by converting the symbol to a block using Symbol#to_proc: You can read it as if it expands to:
->(entry){ entry.send(:join) }
Generally the pattern is:
list = [["2", "2"],["0", "9"],["2", "2"],["2", "7"],["1", "7"],["0", "8"],["0", "1"],["0", "9"]]
# For each item in the list, transform it...
list.collect do |entry|
# ...by joining the bits together into a single string.
entry.join
end
I have a nested array that looks like this:
#nested = [
['1','2','3'],
['1','5','9'],
['1','4','7'],
['3','5','7'],
['3','6','9'],
['7','8','9'],
['4','5','6'],
['2','5','8']
]
I'd like to take a user input of any integer (that 1..9) and find every array that has that input integer.
Not sure how to do it.
Use select:
num_to_search = "9"
#nested.select do |array|
array.include? num_to_search
end
#=> [["1", "5", "9"], ["3", "6", "9"], ["7", "8", "9"]]
I've this familiar question that looks like permutation/combination of the Math world.
How can I achieve the following via ruby?
badges = "1-2-3"
badge_cascade = []
badges.split("-").each do |b|
badge_cascade << b
end
Gives: => ["1", "2", "3"]
But I want it to be is:
=> ["1", "2", "3",
"1-2", "2-3", "3-1", "2-1", "3-2", "1-3",
"1-2-3", "2-3-1", "3-1-2"]
Functional approach:
bs = "1-2-3".split("-")
strings = 1.upto(bs.size).flat_map do |n|
bs.permutation(n).map { |vs| vs.join("-") }
end
#=> ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
You ned to use Array#permutation method in order to get all permutations:
arr = "1-2-3".split '-' # => ["1", "2", "3"]
res = (1..arr.length).reduce([]) { |res, length|
res += arr.permutation(length).to_a
}.map {|arr| arr.join('-')}
puts res.inspect
# => ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
Let me explain the code:
You split string into array passing separator '-' to String#split method
You need all permutations of length 1, 2, 3. Range 1..arr.length represents all these lengths.
You collect an array of all permutations using Enumerable#reduce.
You will get array of arrays here:
[["1"], ["2"], ["3"], ["1", "2"], ["1", "3"], ["2", "1"], ["2", "3"], ["3", "1"], ["3", "2"], ["1", "2", "3"], ["1", "3", "2"], ["2", "1", "3"], ["2", "3", "1"], ["3", "1", "2"], ["3", "2", "1"]]
You transform all subarrays of this array into strings using Array#join with your '-' separator inside of Enumerable#map
Array#permutation(n) will give you all the permutations of length n as an Array of Arrays so you can call this with each length between 1 and the number of digits in badges. The final step is to map these all back into strings delimited with -.
badges = "1-2-3"
badges_split = badges.split('-')
permutations = []
(1..badges_split.size).each do |n|
permutations += badges_split.permutation(n).to_a
end
result = permutations.map { |permutation| permutation.join('-') }
Update: I think Alex's use of reduce is a more elegant approach but I'll leave this answer here for now in case it is useful.