2

I would like the following hash output:

{ 0 => [0,1,2], 1 => [0,1,2], 2 => [0,1,2],
  3 => [3,4,5], 4 => [3,4,5], 5 => [3,4,5],
  6 => [6,7,8], 7 => [6,7,8], 8 => [6,7,8]
}

Intuitively I can just hard code these values in, but I am struggle to figure out how I can dynamically assign each hash key to the appropriate array value.. For instance perhaps creating a 9.times loop?

{ 0 => (0..2).to_a, 1 => (0..2).to_a, 2 => (0..2).to_a,
  3 => (3..5).to_a, 4 => (3..5).to_a, 5 => (3..5).to_a, 
  6 => (6..8).to_a, 7 => (6..8).to_a, 8 => (6..8).to_a 
}

Thanks for any guidance

6 Answers 6

2

With a dynamic upper bound:

count, split = 9, 3
0.upto(count - 1).map do |i|
  [i, [*(i / split * split)...(i / split) * split + split]]
end.to_h
Sign up to request clarification or add additional context in comments.

4 Comments

Very nice solution!
My first time see [*a..b] usage, tried it and seems wonderful. Tried search but can't find it's document, could you give me a keyword to search it? Thanks :)
seems to be the clean and optimised solution with O(n) complexity
@Tiw well, * is a splat operator that basically splats the argument. I am not sure there is a specific paper describing it’s usage inside array initialization.
2

Using modulo operations (%) you can calculate the values of the subarrays:

(0..8).map { |i| [i, (i - i%3 .. i - i%3 + 2).to_a] }.to_h

# => {0=>[0, 1, 2], 1=>[0, 1, 2], 2=>[0, 1, 2], 3=>[3, 4, 5], 4=>[3, 4, 5], 5=>[3, 4, 5], 6=>[6, 7, 8], 7=>[6, 7, 8], 8=>[6, 7, 8]}

Comments

0

Maybe something like this:

[0..2, 3..5, 6..8].each.with_object({}) do |range, result|
  range.each do |ind|
    result[ind] = range.to_a
  end
end

Comments

0
dummy_data = {}
(0..8).to_a.each_slice(3).map{ |m| m.each{|v| dummy_data[v] = m }}

it generates expected dummy data

dummy_data
 => {0=>[0, 1, 2], 1=>[0, 1, 2], 2=>[0, 1, 2], 3=>[3, 4, 5], 4=>[3, 4, 5], 5=>[3, 4, 5], 6=>[6, 7, 8], 7=>[6, 7, 8], 8=>[6, 7, 8]} 

1 Comment

Don’t abuse each for reducing: (0..8).each_slice(3).each_with_object({}) { |m, acc| m.each {|v| acc[v] = m }}.
0
def make_da_hash(n)
  a = (0..n*n-1).to_a
  a.zip(a.each_slice(n).flat_map { |e| [e]*n }).to_h
end

make_da_hash(3)
  #=> {0=>[0, 1, 2], 1=>[0, 1, 2], 2=>[0, 1, 2],
  #    3=>[3, 4, 5], 4=>[3, 4, 5], 5=>[3, 4, 5],
  #    6=>[6, 7, 8], 7=>[6, 7, 8], 8=>[6, 7, 8]} 

make_da_hash(4)
  #=> {0=>[0, 1, 2, 3], 1=>[0, 1, 2, 3], 2=>[0, 1, 2, 3], 3=>[0, 1, 2, 3],
  #    4=>[4, 5, 6, 7], 5=>[4, 5, 6, 7], 6=>[4, 5, 6, 7], 7=>[4, 5, 6, 7],
  #    8=>[8, 9, 10, 11], 9=>[8, 9, 10, 11], 10=>[8, 9, 10, 11],
  #    11=>[8, 9, 10, 11], 12=>[12, 13, 14, 15], 13=>[12, 13, 14, 15],
  #    14=>[12, 13, 14, 15], 15=>[12, 13, 14, 15]} 

1 Comment

Yes, I could change (0..n*n-1) to (0...n*n), but I never use three dots. ¯\_(ツ)_/¯
0
{}.merge(*Array.new(3){|i| (0..8).group_by{|n| n / 3 * 3 + i}})  

Output:

{
  0=>[0, 1, 2],
  3=>[3, 4, 5],
  6=>[6, 7, 8],
  1=>[0, 1, 2],
  4=>[3, 4, 5],
  7=>[6, 7, 8],
  2=>[0, 1, 2],
  5=>[3, 4, 5],
  8=>[6, 7, 8]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.