0

I need to know how you break an array into sub-arrays based on the value of the integers in the array. What I'm trying to do is take a large array and break it into 1-10, 11-20, 21-30...etc and I need to then be able to count those sub arrays so I have numbers that are like "7 integers between 1-10, 6 integers between 11-20, 12 integers between 21-30."

I've got a single line random number generator that will give me my array like the following:

rand_num = (Array.new(200) {(1..100).to_a[rand(100)]})

This gives me my array of 200 hundred random numbers between 1 and 100 and now I need to be able to split them apart according to value and tell how much is in each one.

Then I need it to display those numbers. I've searched everywhere and I want to say you do this with .partition, but I just can't get it to work.

2 Answers 2

2

If your buckets really are that simple then you could use group_by like this:

array.group_by { |n| (n - 1) / 10 }

That will give you Hash like this:

{0=>[1, 2, 3, ...], 1=>[11, 12, 13, ...], ...}

then you just throw in a sort_by to force a nice ordering and a map to summarize the results:

array.group_by { |n| (n - 1) / 10 }.
      sort_by { |k, v| k }.
      map { |n, a| [10 * n + 1 .. 10 * (n + 1), a.length] }

For example:

# The %7 is just an easy way to get a non-uniform set.
>> (1..100).select { |n| n % 7 == 0 }
=> [7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]
>> (1..100).select { |n| n % 7 == 0 }.sort_by { |k, v| k }.group_by { |n| (n - 1) / 10 }.map { |n, a| [10 * n + 1 .. 10 * (n + 1), a.length] }
=> [[1..10, 1], [11..20, 1], [21..30, 2], [31..40, 1], [41..50, 2], [51..60, 1], [61..70, 2], [71..80, 1], [81..90, 1], [91..100, 2]]
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. That works great, I was just wondering why it's giving it to me in seemingly random order. Eg. starts with 31-40, then 41-50, then 91-100, etc.
@user1179092: That's because your input array is in random order and the group_by introduces a Hash which can further mess up the order (depending on the Ruby version). I added a simple sort_by to the mix to force an order.
I have one more question. I'm trying to get it to output in a particular format and it'll be really cool if I can finish this on a single line of code. Is it possible to do what I asked above?
@user1179092: That's a pretty simple modification to the map block, you're going to have to do some work yourself if you want to win the bet.
Alright, the one thing I did find is .map(&:chomp), but I can't seem to position it correctly. It's always just finding an error with it. But thanks for all the help, I'll get it sooner or later.
0
results = {}
rand_num.each do |x| 
  if x%10 == 0
    results[x/10 - 1] = [] unless results.key?(x/10 - 1)
    results[x/10 - 1] << x
  else
    results[x/10] = [] unless results.key?(x/10)
    results[x/10] << x
  end
end

Now in key 0 you have numbers between 1-10, in key 1 between 11-20 etc. p.s. I didn't run this code anywhere so it may have bugs ;)

1 Comment

Is there a way to define 'results' inside the sting. I have a bet with a friend that I can do this in three lines of code. One line to make the array, one to break it into the data like you have and one more line to display the answers. I'm also having troubles trying to discern the pattern in your code to add in the attributes for the rest of the integers. Part of the bet was that I don't do the entire thing on a single line with a dozen semi-colons

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.