views:

64

answers:

3

Hi,

I've got this:

a = [[123,1],[124,1],[125,1],[126,2],[127,3],[128,3]]

And I would like to turn a into b:

  • ordered by value
  • random within array of value

// updated:

b = [[124,123,125],[126],[128,127]]

How to do this in ruby? Im using rails.

A: 

One solution is:

a = [[123,1],[124,1],[125,1],[126,2],[127,3],[128,3]]

a = a.sort {|d, e| d[1] <=> e[1]}

prev = a[0][1]; result = []; group = [];

a.each do |e|
  if e[1] == prev
    group << e[0]
  else
    result << group.shuffle
    group = [e[0]]
    prev = e[1]
  end
end
result << group

p result

run:

$ ruby t.rb
[[125, 123, 124], [126], [127, 128]]
動靜能量
ok, so you would say: randomize a first. Then do a.each as you stated? the random within group is important
Maurice Kroon
then you can add shuffle to group when adding to result
動靜能量
+4  A: 
a.group_by(&:last).
  sort_by(&:first).
  map(&:last).
  map {|el| el.map(&:first).shuffle }
Jörg W Mittag
this is insane!! thank you! wow, 1 sentence, impressive!
Maurice Kroon
Beerlington
doesn't it need to be sorted? If a is `a = [[30,100],[123,1],[124,1],[125,1],[126,2],[127,3],[128,3]]` then the result is `[[30], [123, 124, 125], [126], [128, 127]]`
動靜能量
動靜能量, what do you mean? it is sorted by the second argument right?
Maurice Kroon
@動靜能量: You're right.
Jörg W Mittag
shouldn't the 30 go to the end?
動靜能量
Dave Sims
ah, yes, its morning and im awake now. i see your point. @動靜能量, u're right. @Jörg, thx for improving! I didnt see it as much of a problem as the sorting on the last argument is done by sql. but i'll put it as a security check anyway. @Dave, haha, this rails community is crazy! :) thx!
Maurice Kroon
A: 
a.reduce([]){|m,i|m[i[1]]=(m[i[1]]||[])<<i[0];m}.compact
Lars Haugseth
thx Lars! Though I prefer to have a bit more human language so it actually makes sense to me while re-reading the code some time :)
Maurice Kroon