sort_by { rand } not working

Discussion in 'Ruby' started by Mike Dershowitz, Aug 26, 2007.

  1. Hello:

    I've got an array of arrays that I'd like to sort_by random. each
    individual array is just a hash of a value and then an object. Is there
    some reason why sort_by { rand } wouldn't work? My code is simple (teams
    is populated with a db call):

    @teams.each do |t|
    @all << ["t",t]
    end
    #current not working
    @all.sort_by { rand }

    Any ideas? Am I stretching the limit of the rand function?

    Thanks!

    Mike
    --
    Posted via http://www.ruby-forum.com/.
    Mike Dershowitz, Aug 26, 2007
    #1
    1. Advertising

  2. Mike Dershowitz

    Phrogz Guest

    On Aug 26, 7:25 am, Mike Dershowitz <>
    wrote:
    > @teams.each do |t|
    > @all << ["t",t]
    > end
    > #current not working
    > @all.sort_by { rand }


    #sort_by doesn't modify the original array, it returns a new one.

    Try @all = @all.sort_by{ rand }
    Phrogz, Aug 26, 2007
    #2
    1. Advertising

  3. Mike Dershowitz

    Ken Bloom Guest

    On Sun, 26 Aug 2007 22:25:08 +0900, Mike Dershowitz wrote:

    > Hello:
    >
    > I've got an array of arrays that I'd like to sort_by random. each
    > individual array is just a hash of a value and then an object. Is there
    > some reason why sort_by { rand } wouldn't work? My code is simple (teams
    > is populated with a db call):
    >
    > @teams.each do |t|
    > @all << ["t",t]
    > end
    > #current not working
    > @all.sort_by { rand }


    sort_by returns the sorted list
    sort_by! sorts the list in place

    --Ken

    --
    Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
    Department of Computer Science. Illinois Institute of Technology.
    http://www.iit.edu/~kbloom1/
    Ken Bloom, Aug 26, 2007
    #3
  4. Mike Dershowitz

    Ken Bloom Guest

    On Sun, 26 Aug 2007 09:22:38 -0500, Ken Bloom wrote:

    > On Sun, 26 Aug 2007 22:25:08 +0900, Mike Dershowitz wrote:
    >
    >> Hello:
    >>
    >> I've got an array of arrays that I'd like to sort_by random. each
    >> individual array is just a hash of a value and then an object. Is
    >> there some reason why sort_by { rand } wouldn't work? My code is simple
    >> (teams is populated with a db call):
    >>
    >> @teams.each do |t|
    >> @all << ["t",t]
    >> end
    >> #current not working
    >> @all.sort_by { rand }

    >
    > sort_by returns the sorted list
    > sort_by! sorts the list in place


    Whoops. As soon as I posted, I noticed that there is no sort_by!.

    --Ken

    --
    Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
    Department of Computer Science. Illinois Institute of Technology.
    http://www.iit.edu/~kbloom1/
    Ken Bloom, Aug 26, 2007
    #4
  5. Mike Dershowitz

    botp Guest

    On 8/26/07, Ken Bloom <> wrote:
    > Whoops. As soon as I posted, I noticed that there is no sort_by!.


    try

    sort!{rand}


    kind regards -botp
    botp, Aug 26, 2007
    #5
  6. On Aug 26, 2007, at 12:31 PM, botp wrote:

    > On 8/26/07, Ken Bloom <> wrote:
    >> Whoops. As soon as I posted, I noticed that there is no sort_by!.

    >
    > try
    >
    > sort!{rand}


    That's not a random sort. In fact, it's equivalent to sort! { 1 }:

    >> data =3D (0..9).to_a

    =3D> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >> data.sort! { rand }

    =3D> [9, 5, 0, 6, 2, 7, 4, 8, 3, 1]
    >> data.sort! { rand }

    =3D> [1, 7, 9, 4, 0, 8, 2, 3, 6, 5]
    >> data.sort! { rand }

    =3D> [5, 8, 1, 2, 9, 3, 0, 6, 4, 7]
    >> data =3D (0..9).to_a

    =3D> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >> data.sort! { 1 }

    =3D> [9, 5, 0, 6, 2, 7, 4, 8, 3, 1]
    >> data.sort! { 1 }

    =3D> [1, 7, 9, 4, 0, 8, 2, 3, 6, 5]
    >> data.sort! { 1 }

    =3D> [5, 8, 1, 2, 9, 3, 0, 6, 4, 7]

    It would be better to use:

    data =3D data.sort_by { =85 }

    James Edward Gray II=
    James Edward Gray II, Aug 26, 2007
    #6
  7. botp wrote:
    > On 8/26/07, Ken Bloom <> wrote:
    >> Whoops. As soon as I posted, I noticed that there is no sort_by!.

    >
    > try
    >
    > sort!{rand}
    >
    >
    > kind regards -botp


    That's equivalent to sort! { 1 } and rather predictable (sort/sort!
    expects -1, 0 or 1 as value, rand is 0..1) and hence IMHO pointless.

    Regards
    Stefan
    --
    Posted via http://www.ruby-forum.com/.
    Stefan Rusterholz, Aug 26, 2007
    #7
  8. James Gray wrote:
    > On Aug 26, 2007, at 12:31 PM, botp wrote:
    >
    >> On 8/26/07, Ken Bloom <> wrote:
    >>> Whoops. As soon as I posted, I noticed that there is no sort_by!.

    >>
    >> try
    >>
    >> sort!{rand}

    >
    > That's not a random sort. In fact, it's equivalent to sort! { 1 }:
    >
    > >> data = (0..9).to_a

    > => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    > >> data.sort! { rand }

    > => [9, 5, 0, 6, 2, 7, 4, 8, 3, 1]
    > >> data.sort! { rand }

    > => [1, 7, 9, 4, 0, 8, 2, 3, 6, 5]
    > >> data.sort! { rand }

    > => [5, 8, 1, 2, 9, 3, 0, 6, 4, 7]
    > >> data = (0..9).to_a

    > => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    > >> data.sort! { 1 }

    > => [9, 5, 0, 6, 2, 7, 4, 8, 3, 1]
    > >> data.sort! { 1 }

    > => [1, 7, 9, 4, 0, 8, 2, 3, 6, 5]
    > >> data.sort! { 1 }

    > => [5, 8, 1, 2, 9, 3, 0, 6, 4, 7]
    >
    > It would be better to use:
    >
    > data = data.sort_by { � }
    >
    > James Edward Gray II


    Well, it has the (extremely little) chance of being 0, which introduces
    a very very small randomness :)

    Regards
    Stefan
    --
    Posted via http://www.ruby-forum.com/.
    Stefan Rusterholz, Aug 26, 2007
    #8
  9. James Edward Gray II wrote:
    >
    > It would be better to use:
    >
    > data = data.sort_by { … }


    I was wondering about a crazy idea of mine: "sort!{rand<=>rand}" and
    from my bench results it's a waste of time (it's even dangerous, see
    below). I suspect sort_by begins by mapping the block results and then
    sorts based on the map (it's roughly 4x faster than sort!{ rand <=> rand }).
    sort!{rand<=>rand} obviously can't do that and must call the block each
    time a comparison must be done (I suspect that more rand calls make it
    slower even if it can avoid copying things and instead do in-place
    modifications ... or that the Ruby sort algorithm doesn't like
    comparison results changing...).

    Obviously depending on the sort algorithm used it might not even
    converge on a result (the dangerous part...).

    Lionel
    Lionel Bouton, Aug 26, 2007
    #9
  10. Mike Dershowitz

    Dan Zwell Guest

    Mike Dershowitz wrote:
    > Hello:
    >
    > I've got an array of arrays that I'd like to sort_by random. each
    > individual array is just a hash of a value and then an object. Is there
    > some reason why sort_by { rand } wouldn't work? My code is simple (teams
    > is populated with a db call):
    >
    > @teams.each do |t|
    > @all << ["t",t]
    > end
    > #current not working
    > @all.sort_by { rand }
    >
    > Any ideas? Am I stretching the limit of the rand function?
    >
    > Thanks!
    >
    > Mike


    Mike,

    This has been discussed here before. Your two best choices are:
    @all = @all.sort_by {rand}
    or

    for i in
    j = i+rand(@all.length-i)
    @all, @all[j] = @all[j], @all
    end

    The second one will be faster, but you probably shouldn't care on small
    arrays.

    Dan
    Dan Zwell, Aug 26, 2007
    #10
  11. Dan Zwell wrote:
    >
    > for i in
    > j = i+rand(@all.length-i)
    > @all, @all[j] = @all[j], @all
    > end
    >
    > The second one will be faster, but you probably shouldn't care on
    > small arrays.
    >


    You could even optimize this further with -1 instead of
    (the last loop is a noop), but I agree, this is too much
    pain for the eyes to bother unless it becomes a real performance problem.

    Sorry if this has already been said, in fact I didn't even remember this
    code on the mailing-list at all (too much traffic for me maybe).

    Lionel
    Lionel Bouton, Aug 26, 2007
    #11
  12. Mike Dershowitz

    Dan Zwell Guest

    Lionel Bouton wrote:
    > Dan Zwell wrote:
    >> for i in
    >> j = i+rand(@all.length-i)
    >> @all, @all[j] = @all[j], @all
    >> end
    >>
    >> The second one will be faster, but you probably shouldn't care on
    >> small arrays.
    >>

    >
    > You could even optimize this further with -1 instead of
    > (the last loop is a noop), but I agree, this is too much
    > pain for the eyes to bother unless it becomes a real performance problem.
    >
    > Sorry if this has already been said, in fact I didn't even remember this
    > code on the mailing-list at all (too much traffic for me maybe).
    >
    > Lionel
    >
    >


    Heh, you're right about the noop, and that hasn't been said. This code
    was never on the list in this form--those 4 lines are a condensation of
    something I posted to this list from my algorithms book, and someone's
    suggestion that optimized it further (use parallel assignment instead of
    making a swap() function).

    Dan
    Dan Zwell, Aug 26, 2007
    #12
  13. Lionel Bouton wrote:
    > Dan Zwell wrote:
    >>
    >> for i in
    >> j = i+rand(@all.length-i)
    >> @all, @all[j] = @all[j], @all
    >> end
    >>
    >> The second one will be faster, but you probably shouldn't care on
    >> small arrays.
    >>

    >
    > You could even optimize this further with -1 instead of
    > (the last loop is a noop), but I agree, this is too much
    > pain for the eyes to bother unless it becomes a real performance
    > problem.


    You could even use @all.length.times :) (IMHO more readable, speed wise
    it is faster for small arrays, slower for big arrays, break even is here
    around 100 items).

    Regards
    Stefan
    --
    Posted via http://www.ruby-forum.com/.
    Stefan Rusterholz, Aug 26, 2007
    #13
  14. On 8/26/07, Stefan Rusterholz <> wrote:

    > You could even use @all.length.times :) (IMHO more readable, speed wise
    > it is faster for small arrays, slower for big arrays, break even is here
    > around 100 items).
    >

    @all.each_index { ... } ?
    > Regards
    > Stefan
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
    Logan Capaldo, Aug 27, 2007
    #14
  15. Mike Dershowitz

    Guest

    If you don't mind removing duplicates, Sets are non-ordered, so you
    could do
    s = Set.new
    @all.each do |e| s.add(e) end

    That will be non-ordered, but duplicates will get stripped.

    Tom
    , Aug 27, 2007
    #15
  16. Mike Dershowitz

    Dan Zwell Guest

    wrote:
    > If you don't mind removing duplicates, Sets are non-ordered, so you
    > could do
    > s = Set.new
    > @all.each do |e| s.add(e) end
    >
    > That will be non-ordered, but duplicates will get stripped.
    >
    > Tom
    >
    >
    >


    Non-ordered isn't the same as randomized. Sets most certainly are
    ordered, we (the non-ruby-core-developers) just don't know how. The
    point is that they aren't guaranteed to be random. Try running the above
    code and see--it results in the same ordering each time, regardless of
    the order in which the elements are added. For some data sets, it will
    probably appear more random than others.

    Dan
    Dan Zwell, Aug 27, 2007
    #16
  17. Dan Zwell wrote:
    > Non-ordered isn't the same as randomized.


    I apologize mos sincerely for posting actual code but what about this
    for randomizing:

    def arr_rand(ar)
    arr = []
    while ar.length > 0 do
    x = rand(ar.length)
    arr << ar[x]
    ar.delete_at(x)
    end
    arr
    end

    data = (0..9).to_a

    10.times do
    data = arr_rand(data)
    p data
    end
    --
    Posted via http://www.ruby-forum.com/.
    Lloyd Linklater, Aug 27, 2007
    #17
  18. dang it! I *knew* that I should have been thinking more ruby and less
    pascal. This may look more rubyish:

    def arr_rand(ar)
    arr = []
    while ar.length > 0 {arr << ar.delete_at(rand(ar.length))}
    arr
    end
    --
    Posted via http://www.ruby-forum.com/.
    Lloyd Linklater, Aug 27, 2007
    #18
  19. Mike Dershowitz

    Dan Zwell Guest

    Lloyd Linklater wrote:
    > dang it! I *knew* that I should have been thinking more ruby and less
    > pascal. This may look more rubyish:
    >
    > def arr_rand(ar)
    > arr = []
    > while ar.length > 0 {arr << ar.delete_at(rand(ar.length))}
    > arr
    > end


    Yes, that is fairly simple to understand. But it is equivalent to
    sort_by {rand} in that it does not actually change the array that is
    passed in. How about this variation?

    def randomize!(ary)
    temp = ary.dup
    ary.clear
    ary << temp.delete_at(rand(temp.length)) until temp.empty?
    ary # this line is optional--want to return the array
    # we've just randomized?
    end


    Dan
    Dan Zwell, Aug 27, 2007
    #19
  20. Dan Zwell wrote:
    > Lloyd Linklater wrote:
    >> dang it! I *knew* that I should have been thinking more ruby and less
    >> pascal. This may look more rubyish:
    >>
    >> def arr_rand(ar)
    >> arr = []
    >> while ar.length > 0 {arr << ar.delete_at(rand(ar.length))}
    >> arr
    >> end

    >
    > Yes, that is fairly simple to understand. But it is equivalent to
    > sort_by {rand} in that it does not actually change the array that is
    > passed in.


    Actually, it was different. The sort_by {rand} gives the same sequence
    of shuffling every time you run it. Mine is different every time. I
    get a bang out of the declaration you have. That is a nice touch. I
    also like your use of until temp.empty? That is very Ruby-ish to me.
    :)
    --
    Posted via http://www.ruby-forum.com/.
    Lloyd Linklater, Aug 27, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Gaunnac

    A sort_by descending sort

    Michael Gaunnac, Oct 8, 2004, in forum: Ruby
    Replies:
    8
    Views:
    157
    Brian Candler
    Oct 9, 2004
  2. Patrick Gundlach

    stable sort_by?

    Patrick Gundlach, Dec 13, 2005, in forum: Ruby
    Replies:
    11
    Views:
    192
    Martin DeMello
    Dec 14, 2005
  3. Pat Maddox

    sort_by{rand} doesn't shuffle array

    Pat Maddox, Jan 3, 2006, in forum: Ruby
    Replies:
    4
    Views:
    114
    Mauricio Fernandez
    Jan 3, 2006
  4. 7stud --

    rand() v. rand(0.1) ?

    7stud --, Sep 15, 2007, in forum: Ruby
    Replies:
    6
    Views:
    221
    Morton Goldberg
    Sep 16, 2007
  5. Michel Demazure

    sort_by is not stable ?

    Michel Demazure, Nov 7, 2010, in forum: Ruby
    Replies:
    20
    Views:
    341
    Michel Demazure
    Dec 5, 2010
Loading...

Share This Page