How do I split a string given an array of split positions? - ruby-on-rails

I'm using Ruby 2.4 and Rails 5. I have an array of indexes within a line
[5, 8, 10]
How do I take the above array, and a string, and form anotehr array of strings that are split by the above indexes? FOr instance, if the string is
abcdefghijklmn
and split it based ont eh above indexes, I would have an array with the following strings
abcde
fgh
ij
klmn

Try this
str = "abcdefghijklmn"
positions = [5, 8, 10]
parts = [0, *positions, str.size].each_cons(2).map { |a, b| str[a...b] }
# => ["abcde", "fgh", "ij", "klmn"]
Or,
If the positions are constant and known ahead of runtime (for example if they were the format for a phone number or credit card) just use a regexp
str.match(/(.....)(...)(..)(.*)/).captures
# => ["abcde", "fgh", "ij", "klmn"]

This will get the Job done
str = "abcdefghijklmn"
arr_1 = [5, 8, 10]
arr_2, prev = [], 0
(arr_1.length + 1).times do |x|
if arr_1[x] == nil then arr_1[x] = str.size end
arr_2 << str[prev..arr_1[x] -1]
prev = arr_1[x]
end
p arr_2
---------------------------------------
Program Run Output
["abcde", "fgh", "ij", "klmn"]
---------------------------------------
I hope this Helps

Related

ruby arrays count of most frequent element [duplicate]

This question already has answers here:
How to find an item in array which has the most occurrences [duplicate]
(11 answers)
Closed 6 years ago.
I'm trying to figure out how to find a count of the most frequent element in an array of integers. I can think of a few methods that might be helpful but when I get to writing an expression inside the block I get complete lost on how to compare an element with the next and previous element. Any ideas? All help is really really appreciated!!!
An easy was is to determine all the unique values, convert each to its count in the array, then determine the largest count.
def max_count(arr)
arr.uniq.map { |n| arr.count(n) }.max
end
For example:
arr = [1,2,4,3,2,6,3,4,2]
max_count(arr)
#=> 3
There are three steps:
a = arr.uniq
#=> [1, 2, 4, 3, 6]
b = a.map { |n| arr.count(n) }
#=> [1, 3, 2, 2, 1]
b.max
#=> 3
A somewhat more efficient way (because the elements of arr are enumerated only once) is to use a counting hash:
def max_count(arr)
arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }.values.max
end
max_count(arr)
#=> 3
We have:
a = arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
#=> {1=>1, 2=>3, 4=>2, 3=>2, 6=>1}
b = a.values
#=> [1, 3, 2, 2, 1]
b.max
#=> 3
See Hash::new for an explanation of Hash.new(0). Briefly, if h = Hash.new(0) and h does not have a key k, h[k] will return the default value, which here is zero. h[k] += 1 expands to h[k] = h[k] + 1, so if h does not have a key k, this becomes h[k] = 0 + 1. On the other hand, if, say, h[k] => 2, then h[k] = h[k] + 1 #=> h[k] = 3 + 1.

How to convert an array into a 2D matrix in Lua?

I have the following array of numbers.
arr = {3412323450, 8912745671, 3212367894}
I want to convert it into a simple two-dimensional matrix.
mat = {
{3, 4, 1, 2, 3, 2, 3, 4, 5, 0},
{8, 9, 1, 2, 7, 4, 5, 6, 7, 1},
{3, 2, 1, 2, 3, 6, 7, 8, 9, 4}
}
Initially, I would iterate over arr, convert it into a string, then split the string, iterate over each string char and convert it back to number storing every row and number in mat accordingly. This would be really ugly.
Is there a more conventional method to convert an array into a matrix in
Lua?
Is there a luarock package that people use frequently to convert an array to a matrix?
Personally I think converting to a string and grabbing all of the digits is far prettier than the alternatives (massively dividing by 10, or any other elaborate means you can think of). This is especially true if you wrap the operations up in functions, so your conversions are not constantly appearing throughout your code.
function Digits(n)
local digits = {}
for d in tostring(n):gmatch('%d') do
digits[#digits+1] = tonumber(d)
end
return digits
end
function ArrayToMatrix(array)
local matrix = {}
for i,v in ipairs(array) do
matrix[i] = Digits(v)
end
return matrix
end
Ok, here is my try.
arr = {3412323450, 8912745671, 3212367894}
function arr2matrix(arr)
local mat = {}
for i, row in ipairs(arr) do
mat[i] = {}
local j = 0
row_str = string.gsub(row, '%d', '%0 ')
for c in string.gmatch(row_str, '%S') do
j = j + 1
mat[i][j] = tonumber(c)
end
end
return mat
end
-- checking the result
m = arr2matrix(arr)
for i=1, #m do
for j=1, #m[i] do
io.write(m[i][j]..',')
end
io.write('\n')
end
Running the above gives:
3,4,1,2,3,2,3,4,5,0,
8,9,1,2,7,4,5,6,7,1,
3,2,1,2,3,6,7,8,9,4,

Creating a range from one column

I have a column called "Marks" which contains values like
Marks = [100,200,150,157,....]
I need to assign Grades to those marks using the following key
<25=0, <75=1, <125=2, <250=3, <500=4, >500=5
If Marks < 25, then Grade = 0, if marks < 75 then grade = 1.
I can sort the results and find the first record that matches using Ruby's find function. Is it the best method ? Or is there a way by which I can prepare a range using the key by adding Lower Limit and Upper Limit columns to the table and by populating those ranges using the key? Marks can have decimals too Ex: 99.99
Without using Rails, you could do it like this:
marks = [100, 200, 150, 157, 692, 12]
marks_to_grade = { 25=>0, 75=>1, 125=>2, 250=>3, 500=>4, Float::INFINITY=>5 }
Hash[marks.map { |m| [m, marks_to_grade.find { |k,_| m <= k }.last] }]
#=> {100=>2, 200=>3, 150=>3, 157=>3, 692=>5, 12=>0}
With Ruby 2.1, you could write this:
marks.map { |m| [m, marks_to_grade.find { |k,_| m <= k }.last] }.to_h
Here's what's happening:
Enumerable#map (a.k.a collect) converts each mark m to an array [m, g], where g is the grade computed for that mark. For example, when map passes the first element of marks into its block, we have:
m = 100
a = marks_to_grade.find { |k,_| m <= k }
#=> marks_to_grade.find { |k,_| 100 <= k }
#=> [125, 2]
a.last
#=> 2
so the mark 100 is mapped to [100, 2]. (I've replaced the block variable for the value of the key-value pair with the placeholder _ to draw attention to the fact that the value is not being used in the calculation within the block. One could also use, say, _v as the placeholder.) The remaining marks are similarly mapped, resulting in:
b = marks.map { |m| [m, marks_to_grade.find { |k,_| m <= k }.last] }
#=> [[100, 2], [200, 3], [150, 3], [157, 3], [692, 5], [12, 0]]
Lastly
Hash[b]
#=> {100=>2, 200=>3, 150=>3, 157=>3, 692=>5, 12=>0}
or, for Ruby 2.1+
b.to_h
#=> {100=>2, 200=>3, 150=>3, 157=>3, 692=>5, 12=>0}
You can make use of update_all:
Student.where(:mark => 0...25).update_all(grade: 0)
Student.where(:mark => 25...75).update_all(grade: 1)
Student.where(:mark => 75...125).update_all(grade: 2)
Student.where(:mark => 125...250).update_all(grade: 3)
Student.where(:mark => 250...500).update_all(grade: 4)
Student.where("mark > ?", 500).update_all(grade: 5)

Select method with args separated by double-pipes only checking first element... Alternative?

I have a bit of broken legacy code I have to fix. Its purpose was to take a large array and return elements that have a particular sector number.
Here's a simplified version of the code in the app. Goal: return any instance of 1 or 3 in array:
array = [1,1,2,2,3,3].select{|num| num == (1 || 3) }
But the return value is simply #=> [1, 1] when the desired return was #=> [1, 1, 3, 3]
Basically, what I'm looking for is the Ruby equivalent to the following SQL query:
SELECT num FROM array
WHERE num IN (1, 3);
Ruby 1.8.7, Rails 2.3.15
Do as below to meet your need :
array = [1,1,2,2,3,3]
array.select{|num| [1,3].include? num }
# => [1, 1, 3, 3]
See why you got only [1,1].
1 || 3 # => 1
1 || 3 will always returns 1, thus num == 1 is evaluated as true when select is passing only 1. As a result you got [1,1].

Splitting/Slicing array in ruby

I've found this similar two questions to the one I'm about to ask:
Split array up into n-groups of m size?
and
Need to split arrays to sub arrays of specified size in Ruby
This splits array into three arrays with each array having three elements :
a.each_slice(3) do |x,y,z|
p [x,y,z]
end
So if I do this (my array size is 1000) :
a.each_slice(200) do |a,b,c,d,e|
p "#{a} #{b} #{c} #{d} #{e}"
end
This should split my array into 5 arrays each having 200 members? But it doesn't?
What I actually need to do is to put 200 random elements into 5 arrays, am I on the right track here, how can I do this?
Enumerable#each_slice
If you provide a single argument to the block of each_slice then it will fill that argument with an array of values less than or equal to the given argument. On the last iteration if there are less than n values left then the array size will be whatever is left.
If you provide multiple arguments to the block of each_slice then it will fill those values with the values from the source array. If the slice size is greater than the number of arguments given then some values will be ignored. If it is less than the number of arguments than the excess arguments will be nil.
a = (1..9).to_a
a.each_slice(3) {|b| puts b.inspect }
[1,2,3]
[4,5,6]
[7,8,9]
a.each_slice(4) {|b| puts b.inspect }
[1,2,3,4]
[5,6,7,8]
[9]
a.each_slice(3) {|b,c,d| puts (b + c + d)}
6 # 1 + 2 + 3
15 # 4 + 5 + 6
24 # 7 + 8 + 9
a.each_slice(3) {|b,c| puts (b + c)}
3 # 1 + 2, skips 3
9 # 4 + 5, skips 6
15 # 7 + 8, skips 9
a.each_slice(2) {|b,c| puts c.inspect}
2
4
6
8
nil
a.each_slice(3) {|b,c,d,e| puts e.inspect}
nil
nil
nil
irb(main):001:0> a= (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):002:0> a.sample(3)
=> [5, 10, 1]
irb(main):003:0> (1..3).map{ a.sample(3) }
=> [[6, 2, 5], [8, 7, 3], [4, 5, 7]]
irb(main):004:0>
Actually you will return a string with the five elements inserted in it.
You can try something:
a1 = [], a2 = [], a3 = [], a4 = [], a5 = []
a.each_slice(5) do |a,b,c,d,e|
a1 << a
a2 << b
a3 << c
a4 << d
a5 << e
end
You will end up with five arrays containing 200 elements each.
I used the simplest possible syntax to make it clear, you can
make it much more condensed.
If you want to assign that result to 5 different arrays, you could use the splat operator,like this:
a,b,c,d,e = *(1..1000).each_slice(200).to_a

Resources