Say I made a Hash like this: ["ab" => "a", "ac" => "a", "cd" => "c", "ce" => "c", "df" => "d"]
and I need to split this into 3 arrays like these: ["ab", "ac"], ["cd", "ce"], ["df"]. Split my Hash into 3 arrays based on keys which has same values.
How can I do this?
you can use group by on a hash and group by the values this will return a hash with the value as a key and all hashes with the same value in an array then transform the values and take the first element in each array of that value (wich would be the key of the original objects)
hash.group_by { |key, value| value }.transform_values(&:first).values
[1] pry(main)> {"ab" => "a", "ac" => "a", "cd" => "c", "ce" => "c", "df" => "d"}.group_by { |key, value| value }.transform_values(&:first).values
=> [["ab", "a"], ["cd", "c"], ["df", "d"]]
Input
a={"ab" => "a", "ac" => "a", "cd" => "c", "ce" => "c", "df" => "d"}
Code
p a.group_by{|_,v|v}
.values
.map{|arr|arr.map(&:first)}
output
[["ab", "ac"], ["cd", "ce"], ["df"]]
I need to reorganize an array into slices of 2 elements and then sort each slice alphabetically using each_slice
I've managed to get the each_slice correctly but I can seem to then sort each sub array.
What am I doing wrong here?
array.each_slice(2).to_a { |el| el = el.sort}
You just need to create a new array with the output that you want.
For instance:
# $ array = ["b", "a", "d", "c", "k", "l", "p"]
arr = []
array.each_slice(2) { |el| arr << el.sort}
# $ arr
# => [["a", "b"], ["c", "d"], ["k", "l"], ["p"]]
EDIT:
Pointed in the comments (by #mu is too short), you can also do:
arr = array.each_slice(2).map(&:sort)
I'm fairly new to ruby and it's my first question here on stackoverflow so pardon me if I'm being a complete noob.
The code which i am working with contains this line -
puts (6..6).flat_map{|n| ('a'..'z').to_a.combination(n).map(&:join)}
What the code does is that its starts printing each of the combinations starting from "abcdef" and continues till the end (which i have never seen as it has 26^6 combinations).
Of course having an array of that size (26^6) is unimaginable hence I was wondering if there is any way by which i can get next combination in a variable, work with it, and then continue on to the next combination ?
For example I calculate the first combination as "abcdef" and store it in a variable 'combo' and use that variable somewhere and then the next combination is calculated and "abcdeg" is stored in 'combo' and hence the loop continues ?
Thanks
(6..6).flat_map { |n| ... } doesn't do much. Your code is equivalent to:
puts ('a'..'z').to_a.combination(6).map(&:join)
To process the values one by one, you can pass a block to combination:
('a'..'z').to_a.combination(6) do |combo|
puts combo.join
end
If no block is given, combination returns an Enumerator that can be iterated by calling next:
enum = ('a'..'z').to_a.combination(6)
#=> #<Enumerator: ["a", "b", "c", ..., "w", "x", "y", "z"]:combination(6)>
enum.next
#=> ["a", "b", "c", "d", "e", "f"]
enum.next
#=> ["a", "b", "c", "d", "e", "g"]
enum.next
#=> ["a", "b", "c", "d", "e", "h"]
Note that ('a'..'z').to_a.combination(6) will "only" yield 230,230 combinations:
('a'..'z').to_a.combination(6).size
#=> 230230
As opposed to 26 ^ 6 = 308,915,776. You are probably looking for repeated_permutation:
('a'..'z').to_a.repeated_permutation(6).size
#=> 308915776
Another way to iterate from "aaaaaa" to "zzzzzz" is a simple range:
('aaaaaa'..'zzzzzz').each do |combo|
puts combo
end
Or manually by calling String#succ: (this is what Range#each does under the hood)
'aaaaaa'.succ #=> "aaaaab"
'aaaaab'.succ #=> "aaaaac"
'aaaaaz'.succ #=> "aaaaba"
I need to convert data from a string to an array. The string looks like this:
{a,b,c{1,2,3},d,e,f{11,22,33},g}
The array that I want to receive should look like this:
[a, b, c1, c2, c3, d, e, f11, f22, f33, g]
I tried to use the split method but it works poorly.
arr = str.split(' ');
keys = arr[0][2..-2]
keys = keys.split(',')
Do you have any ideas how it could be implemented?
Here's what I'd use:
string = '{a,b,c{1,2,3},d,e,f{11,22,33},g}'
array = string.scan(/[a-z](?:{.+?})?/).flat_map{ |s|
if s['{']
prefix = s[0]
values = s.scan(/\d+/)
([prefix] * values.size).zip(values).map(&:join)
else
s
end
}
array # => ["a", "b", "c1", "c2", "c3", "d", "e", "f11", "f22", "f33", "g"]
Here's how it works:
string.scan(/[a-z](?:{.+?})?/) # => ["a", "b", "c{1,2,3}", "d", "e", "f{11,22,33}", "g"]
returns the string broken into chunks, looking for a single letter followed by an optional string of { with some text then }.
values = s.scan(/\d+/) # => ["1", "2", "3"], ["11", "22", "33"]
As it's running in flat_map, if { is found, the numbers are scanned out.
([prefix] * values.size).zip(values).map(&:join) # => ["c1", "c2", "c3"], ["f11", "f22", "f33"]
And then an array of the prefix, with the same number of elements as there are values is created and zipped together, resulting in:
[["c", "1"], ["c", "2"], ["c", "3"]], [["f", "11"], ["f", "22"], ["f", "33"]]
The join glues those sub-arrays together. And flat_map flattens any subarrays created so the resulting output is a single array.
You need to arr = str.split(',') in the first step, because there is no whitespace between the values.
Also keep in mind you have {} to handle too.
This worked for me with simple regex and gsubing (though Tin Man's solution is better ruby):
def my_string_to_array(input_string)
groups = input_string.scan(/\w+\{.*?\}/)
groups.each do |group|
modified = group.gsub(',', ",#{group.match(/\w+/)[0]}").delete("{}")
input_string.gsub!(group, modified)
end
created_array = input_string.delete("{}").split(',')
end
string = '{a,b,c{1,2,3},d,e,f{11,22,33},g}'
my_string_to_array(string)
=> ["a", "b", "c1", "c2", "c3", "d", "e", "f11", "f22", "f33", "g"]
The way it works is that it first finds the groups having alphabets followed by braces and digits (like c{1,2,3})
For each such group, it modifies it by gsubing ',' with ',<alphabet>' and removing the braces.
Next, it replaces these groups with the modified ones in the original string.
And finally it removes the starting and ending braces in the original string, and converts it into an array.
I want to pull two values out from an array based on their index.
Unfortunately this fails when the last index is zero and I don't undertand why.
my_array = ["a", "b", "c", "d", "e", "f", "g"]
my_array[1,2]
# => ["b", "c"]
my_array[0,2]
# => ["a", "b"]
my_array[2,0]
# => []
Why does the last allocation fail to pull out elements 2 and 0?
I suspect my operation is not in fact doing what I think at all since adding a third index makes the whole thing fail:
my_array[1,2,3]
# => ArgumentError: wrong number of arguments (3 for 1..2)
What am I actually doing with the array[var1, var2] syntax and what should I be doing?
my_array[start,length][docs] is the slice syntax:
returns a subarray starting at start and continuing for length elements
This is a short syntax for my_array.slice(start, length);
You should do this instead:
my_array.values_at(2, 0)
=> ["c", "a"]
See Array#values_at and Array#slice