ruby working on array elements in groups of four
You can enumerate in groups of 4 for an array:
>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].each_slice(4) {|a| p a}
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
So you can try something like
elements.each_slice(4) do | batch |
batch.each do | element |
threads.push(Thread.new{process(element)}}
end
(do stuff to check to see if the threads are done, otherwise wait )
end
Its may not be what you need, though - I have been up since 3 AM and I only had a couple of hours sleep. :/
Group Elements by Each in Array
Here is another way :
array = [1, 1, 2, 3, 3, 1, 5, 6, 2]
array.group_by(&:itself).values
# => [[1, 1, 1], [2, 2], [3, 3], [5], [6]]
Look #itself
method.
If you have not asked above, then #slice_when
is your way to go :
array.slice_when { |i,j| i != j }.to_a
# => [[1, 1], [2], [3, 3], [1], [5], [6], [2]]
array.slice_when { |i,j| i != j }.each { |n| p "do_something_with_#{n}" }
# "do_something_with_[1, 1]"
# "do_something_with_[2]"
# "do_something_with_[3, 3]"
# "do_something_with_[1]"
# "do_something_with_[5]"
# "do_something_with_[6]"
# "do_something_with_[2]"
Group by, array of arrays in ruby
Use following
some_array.group_by{|a| [a[0], a[1]]}
.map{|key, value| key + [value.map(&:last)]}
.flatten(1)
For multiple values in group by
2.3.1 :046 > some_array = [["FANUC CORP", "100048", 9], ["FANUC CORP", "100048", 26]
, ["FANUC CORP", "100048", 23], ["FANUC CORP", "100048", 111]
, ["FANUC CORP", "100049", 19],["FANUC CORP", "100049", 126],
["FANUC CORP", "100049", 123], ["FANUC CORP", "100049", 1111]]
=> [["FANUC CORP", "100048", 9], ["FANUC CORP", "100048", 26],
["FANUC CORP", "100048", 23], ["FANUC CORP", "100048", 111],
["FANUC CORP", "100049", 19], ["FANUC CORP", "100049", 126],
["FANUC CORP", "100049", 123], ["FANUC CORP", "100049", 1111]]
2.3.1 :047 > some_array.group_by{|a| [a[0], a[1]]}
.map{|key, value| key + [value.map(&:last)]}
.flatten(1)
=> ["FANUC CORP", "100048", [9, 26, 23, 111],
"FANUC CORP", "100049", [19, 126, 123, 1111]]
Group every n-th element of array
Nick Veys' answer is most straightforward, but here is another way.
array.group_by.with_index{|_, i| i % 3}.values
#=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Selecting group of elements from array which satisfies specific condition
if the order doesn't matter (I mean ([4,1]==[4,1])) I have a better solution to bruteforcing combinations.
This is a bruteforcing algorithm
def bruteforcing(arr)
arr.combination(2).find_all{ |x, y| x + y == 5 }.uniq
end
This is a better solution (I'ts just an example you could improve). The main idea is to order the Array and search pair by the opposite extremes at first, and stop the search if the sum of values is mayor than 5.
def search(arr)
ret=[]
arr.sort!
while arr != []
current = arr.pop
arr.each.with_index do |value, index|
if current + value == 5
ret << [value,current]
arr.delete_at(index)
break
elsif current+value > 5
break
end
end
end
ret
end
This is my search.rb (with benchmark)
require "benchmark"
def bruteforcing(arr)
arr.combination(2).find_all{ |x, y| x + y == 5 }.uniq
end
def search(arr)
ret=[]
arr.sort!
while arr != []
current = arr.pop
arr.each.with_index do |value, index|
if current + value == 5
ret << [value,current]
arr.delete_at(index)
break
elsif current+value > 5
break
end
end
end
ret
end
def bench_times(n)
Benchmark.bm do |x|
puts "behc n times #{n}."
x.report { n.times{bruteforcing( [1,2,3,4,3,2,4,1,2] ) } }
x.report { n.times{ search( [1,2,3,4,3,2,4,1,2] ) } }
end
end
def bench_elements(n)
puts "bench with #{n} elements."
Benchmark.bm do |x|
a=[]
1_000.times { a<<rand(1..4) }
x.report { bruteforcing(a) }
a=[]
1_000.times { a << rand(1..4) }
x.report { search(a) }
end
end
puts bruteforcing([1,2,3,4,3,2,4,1,2]).to_s
puts search([1,2,3,4,3,2,4,1,2]).to_s
bench_times 1
bench_times 5
bench_times 1_000
bench_times 1_000_000
bench_elements(100)
bench_elements(1_000)
bench_elements(100_000)
bench_elements(1_000_000)
The output:
[[1, 4], [2, 3], [3, 2], [4, 1]]
[[1, 4], [1, 4], [2, 3], [2, 3]]
user system total real
behc n times 1.
0.000000 0.000000 0.000000 ( 0.000036)
0.000000 0.000000 0.000000 ( 0.000013)
user system total real
behc n times 5.
0.000000 0.000000 0.000000 ( 0.000118)
0.000000 0.000000 0.000000 ( 0.000037)
user system total real
behc n times 1000.
0.020000 0.000000 0.020000 ( 0.017804)
0.010000 0.000000 0.010000 ( 0.006673)
user system total real
behc n times 1000000.
16.580000 0.020000 16.600000 ( 16.583692)
5.970000 0.000000 5.970000 ( 5.968241)
bench with 100 elements.
user system total real
0.210000 0.010000 0.220000 ( 0.213506)
0.000000 0.000000 0.000000 ( 0.000863)
bench with 1000 elements.
user system total real
0.210000 0.000000 0.210000 ( 0.212349)
0.000000 0.000000 0.000000 ( 0.001539)
bench with 100000 elements.
user system total real
0.200000 0.000000 0.200000 ( 0.201456)
0.000000 0.000000 0.000000 ( 0.001067)
bench with 1000000 elements.
user system total real
0.190000 0.010000 0.200000 ( 0.199400)
0.010000 0.000000 0.010000 ( 0.000801)
How to group array elements by index?
You can use slice_after
to slice the array after each item whose index is in idx
:
idx = [1, 5, 7]
arr = %w[a b c d e f g h i j k]
arr.enum_for(:slice_after).with_index { |_, i| idx.include?(i) }.to_a
#=> [["a", "b"], ["c", "d", "e", "f"], ["g", "h"], ["i", "j", "k"]]
That enum_for
is (unfortunately) needed to chain slice_after
and with_index
.
Ruby split array into X groups
You can make your own method, here's a basic idea:
class Array
def my_group(x)
start = 0
size = (self.size() / Float(x)).ceil
while x > 0
yield self[start, size]
size = ((self.size() - 1 - start) / Float(x)).ceil
start += size
x -= 1
end
end
end
%w(1 2 3 4 5 6 7 8 9 10).my_group(3) {|group| p group}
# =>["1", "2", "3", "4"]
# =>["4", "5", "6"]
# =>["7", "8", "9"]
How to group identical elements in Ruby array
Here is how to do that in Ruby.
array.group_by{ |x| x }.values
How to iterate over an array in overlapping groups of n elements?
You can add nil
as the first element of your arr
and use Enumerable#each_cons
method:
arr.unshift(nil).each_cons(2).map { |first, second| [first, second] }
# => [[nil, "one"], ["one", "two"], ["two", "three"]]
(I'm using map
here to show what exactly is returned on each iteration)
Ruby group_by in array of arrays
fruits.group_by {|(fruit, day)| fruit }.map {|fruit, match| [fruit, match.count] }
Related Topics
Optimization for Finding Perfect-Square Algorithm
How to Globally Configure Rspec to Keep the '--Color' and '--Format Specdoc' Options Turned On
Ruby Metaprogramming Online Tutorial
Finding What Is Common to Two Arrays
How to Dump an Http Request from Within Sinatra
Using Htaccess Password Protection on Rails
Reraise (Same Exception) After Catching an Exception in Ruby
How to Create a Ruby Date Object from a String
Include Params/Request Information in Rails Logger
Sidekiq Configuration for Multiple Environments
How to Make Nokogiri Not to Convert &Nbsp; to Space
Rails 4.0.1 on Heroku, Can't Create Database
Can't Install Ruby-Debug-Base19X Gem
How to Manage Ruby Threads So They Finish All Their Work
Is Ruby on Rails (Or at Least the Community) Dying
What Is the Argument Against Using Before, Let and Subject in Rspec Tests