Get all overlapping matches of any length - ruby

I'm trying to achieve:
'abc'.scan(regex) #=> ['a', 'b', 'c', 'ab', 'bc', 'abc']
It can be done like this:
(1..'abc'.size).map {|l| 'abc'.scan /(?=(\w{#{l}}))/}.flatten
#=> ["a", "b", "c", "ab", "bc", "abc"]
But I would like to do it in one regex expression.

What about without regex?:
string = 'abc'
p (1..string.size).flat_map { |e| string.chars.each_cons(e).map(&:join) }
# ["a", "b", "c", "ab", "bc", "abc"]

Related

Split string by regex in Ruby

I need to split a string by commas that are outside brackets. I have this string:
'a,b,c,d[a,b,c[a,b]],e'
and my split needs to return:
['a', 'b', 'c', 'd[a,b,c[a,b]]', 'e']
How can I do that?
'a,b,c,d[a,b,c[a,b]],e'
.scan(/(?:\[[^\]]*\]|[^,])+/)
# => ["a", "b", "c", "d[a,b,c[a,b]]", "e"]
'a,[a][b],e'
.scan(/(?:\[[^\]]*\]|[^,])+/)
# => ["a", "[a][b]", "e"]

How do I split on multiple conditions?

With Ruby how do I split on either one of tow conditions -- wheter there are 3 or more spaces or a tab charadter? I tried this
2.4.0 :003 > line = "a\tb\tc"
=> "a\tb\tc"
2.4.0 :004 > line.split(/([[:space:]][[:space:]][[:space:]]+|\t)/)
=> ["a", "\t", "b", "\t", "c"]
but as you can see, the tab character itself is getting included in my results. The results should be
["a", "b", "c"]
What about just split?
p "a\tb\tc".split
# ["a", "b", "c"]
p "a\tb\tc\t\tc\t\t\t\t\t\t\tc\ts\ts\tt".split
# ["a", "b", "c", "c", "c", "s", "s", "t"]
Although that doesn't split when there are three 3 or more white spaces, this might work:
p "a\tb\tc\t\tc\t\t\ t\t\tc\ts\ts\tt".split(/\s{3,}|\t/)
# => ["a", "b", "c", "c", "t", "c", "s", "s", "t"]
line = "aa bb cc\tdd"
line.split /\p{Space}{3,}|\t+/
#⇒ ["aa bb", "cc", "dd"]

Group by identity in Ruby

How does Ruby's group_by() method group an array by the identity (or rather self) of its elements?
a = 'abccac'.chars
# => ["a", "b", "c", "c", "a", "c"]
a.group_by(&:???)
# should produce...
# { "a" => ["a", "a"],
# "b" => ["b"],
# "c" => ["c", "c", "c"] }
In a newer Ruby (2.2+?),
a.group_by(&:itself)
In an older one, you still need to do a.group_by { |x| x }
Perhaps, this will help:
a = 'abccac'.chars
a.group_by(&:to_s)
#=> {"a"=>["a", "a"], "b"=>["b"], "c"=>["c", "c", "c"]}
Alternatively, below will also work:
a = 'abccac'.chars
a.group_by(&:dup)
#=> {"a"=>["a", "a"], "b"=>["b"], "c"=>["c", "c", "c"]}

Test if elements of one array are included in another

I have the following arrays:
passing_grades = ["A", "B", "C", "D"]
student2434 = ["F", "A", "C", "C", "B"]
and I need to verify that all elements in the student array are included in the passing_grades array. In the scenario above, student2434 would return false. But this student:
student777 = ["C", "A", "C", "C", "B"]
would return true. I tried something like:
if student777.include? passing_grades then return true else return false end
without success. Any help is appreciated.
PASSING_GRADES = ["A", "B", "C", "D"]
def passed?(grades)
(grades - PASSING_GRADES).empty?
end
similar to what CDub had but without bug. more readable in my opinion
You could have a method that does the difference of the arrays, and if any results are present, they didn't pass:
PASSING_GRADES = ["A", "B", "C", "D"]
def passed?(grades)
grades.all? {|grade| PASSING_GRADES.include?(grade)}
end
Example:
1.9.3-p484 :117 > student777 = ["C", "A", "C", "C", "B"]
=> ["C", "A", "C", "C", "B"]
1.9.3-p484 :118 > passed?(student777)
=> true
1.9.3-p484 :118 > passed?(student2434)
=> false

Ruby Hash to array of values

I have this:
hash = { "a"=>["a", "b", "c"], "b"=>["b", "c"] }
and I want to get to this: [["a","b","c"],["b","c"]]
This seems like it should work but it doesn't:
hash.each{|key,value| value}
=> {"a"=>["a", "b", "c"], "b"=>["b", "c"]}
Any suggestions?
Also, a bit simpler....
>> hash = { "a"=>["a", "b", "c"], "b"=>["b", "c"] }
=> {"a"=>["a", "b", "c"], "b"=>["b", "c"]}
>> hash.values
=> [["a", "b", "c"], ["b", "c"]]
Ruby doc here
I would use:
hash.map { |key, value| value }
hash.collect { |k, v| v }
#returns [["a", "b", "c"], ["b", "c"]]
Enumerable#collect takes a block, and returns an array of the results of running the block once on every element of the enumerable. So this code just ignores the keys and returns an array of all the values.
The Enumerable module is pretty awesome. Knowing it well can save you lots of time and lots of code.
It is as simple as
hash.values
#=> [["a", "b", "c"], ["b", "c"]]
this will return a new array populated with the values from hash
if you want to store that new array do
array_of_values = hash.values
#=> [["a", "b", "c"], ["b", "c"]]
array_of_values
#=> [["a", "b", "c"], ["b", "c"]]
hash = { :a => ["a", "b", "c"], :b => ["b", "c"] }
hash.values #=> [["a","b","c"],["b","c"]]
There is also this one:
hash = { foo: "bar", baz: "qux" }
hash.map(&:last) #=> ["bar", "qux"]
Why it works:
The & calls to_proc on the object, and passes it as a block to the method.
something {|i| i.foo }
something(&:foo)

Resources