SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Miami, FL
    Posts
    92
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Quick array question

    Hey guys,

    This may be something that's obvious, but I have a question about sorting through arrays. Let's say I have an array as follows:

    Code:
    a = [ "a", "b", "b", "b", "c", "d", "d", "e" ]
    Simple enough. Now, if I wanted to sort through it by having similar values in highest amounts first (there are 4 Bs and 2 Ds as opposed to the others) so my array ends up like this:

    Code:
    a = [ "b", "b", "b", "d", "d", "a", "c", "e" ]
    How would I go about doing that? Thanks.
    http://shownd.com - Your free online design portfolio.
    http://rehashclothes.com - Swap your clothes.
    http://orpheuxdesign.com - My design studio.

  2. #2
    SitePoint Enthusiast
    Join Date
    May 2008
    Posts
    84
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Count the occurance of each of the characters and then rewrite the array.

  3. #3
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Miami, FL
    Posts
    92
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was looking for something more along the lines of a method to use, because I can count the number of items to my heart's content but I still don't know how to sort the array.
    http://shownd.com - Your free online design portfolio.
    http://rehashclothes.com - Swap your clothes.
    http://orpheuxdesign.com - My design studio.

  4. #4
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As a nice unreadable one-liner:

    Code ruby:
    def sort_by_occurrences(xs)
      xs.inject(Hash.new(0)){|h,x| h[x] += 1; h}.sort_by{|x,n| n}.reverse.map{|(x,n)| [x]*n}.flatten
    end

    Explained in the comments:
    Code ruby:
    def sort_by_occurrences(xs)
      counts = Hash.new(0) # a hash table that maps elements of xs to the number of times the element appears in xs
      for x in xs
        counts[x] += 1
      end
      counts. # counts now is {"a"=>1, "b"=>3, "c"=>1, "d"=>2, "e"=>1}
      sort_by{|x, count| count}. # sort the elements by the number of times they appear in increasing order: [["a", 1], ["e", 1], ["c", 1], ["d", 2], ["b", 3]]
      reverse. # reverse the array because we want elements that appear most first (in decreasing order)
      map{|(x,count)| [x]*count}. # replicate each element count times: [["b", "b", "b"], ["d", "d"], ["c"], ["e"], ["a"]]
      flatten # put them all in one array
    end

  5. #5
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    maybe simpler
    Code:
    ary = [ "a", "b", "b", "b", "c", "d", "d", "e" ]
    count = Hash.new(0)
    ary.each { |e| count[e] += 1 }
    puts ary.sort { |x, y| count[y] - count[x] }

  6. #6
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Miami, FL
    Posts
    92
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks guys. I started to do something similar a few minutes ago then checked this thread. Good to see I was at least on the right track :-)
    http://shownd.com - Your free online design portfolio.
    http://rehashclothes.com - Swap your clothes.
    http://orpheuxdesign.com - My design studio.

  7. #7
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Stereofrog, that's a much more elegant solution!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •