<?xml version="1.0" encoding="UTF-8"?>
<code>
  <code>class Item
  def raw_tag_list; "one, two, three, four, five"; end
  def public_tags; [&lt;#Tag name=two&gt;, &lt;#Tag name=five&gt;, &lt;#Tag name=one&gt;, &lt;#Tag name=four&gt;, &lt;#Tag name=three&gt;]; end

  def tags
    return Array.new if raw_tag_list.nil?

    # Get the raw tag list, split, squish (removed whitespace), and add each to raw_tag_array
    # Make sure we skip if the array already has that tag name (remove any duplicates that occur)
    raw_tag_array = Array.new
    raw_tag_list.split(',').each do |raw_tag|
      next if raw_tag_array.include?(raw_tag.squish)
      raw_tag_array &lt;&lt; raw_tag.squish
    end

    tags = Array.new

    # grab all the tag objects
    tags_out_of_order = public_tags
    if tags_out_of_order.size &gt; 0
      # resort them to match raw_tag_list order
      raw_tag_array.each do |tag_name|
        tag = tags_out_of_order.select { |tag| tag.name == tag_name }
        tags &lt;&lt; tag
      end
      # at this point, we have an array, with arrays of object  [[tag], [tag], [tag]]
      # use compact to remove any nil objects, and flatten to convert it to [tag, tag, tag]
      tags = tags.compact.flatten
    end

    tags
  end
end</code>
  <comment>Is there a faster way to do this? I need to sort an array of tags according to the order of tags in a string. At the moment, I make the array then select as go through. But this is slow. Is there a fancy ruby alternative?</comment>
  <created-at type="datetime">2009-03-30T22:48:23+00:00</created-at>
  <id type="integer">807</id>
  <language>Ruby</language>
  <permalink>tag-ordering-code</permalink>
  <refactors-count type="integer">12</refactors-count>
  <title>Tag ordering code</title>
  <trackback-url></trackback-url>
  <updated-at type="datetime">2009-04-01T17:47:43+00:00</updated-at>
  <user-id type="integer">1425</user-id>
  <refactors type="array">
    <refactor>
      <code>class Tag
  def initialize name
    @name = name  
  end
  
  def self.parse string
    string.split(',').map { |tag| Tag.new(tag.strip) }
  end
end

params = { :tags =&gt; 'foo,bar,  some more bar, whoop' }
p Tag.parse(params[:tags])
# =&gt; [#&lt;Tag:0x27a88 @name="foo"&gt;, #&lt;Tag:0x27a60 @name="bar"&gt;, #&lt;Tag:0x27a38 @name="some more bar"&gt;, #&lt;Tag:0x27a10 @name="whoop"&gt;]</code>
      <code-id type="integer">807</code-id>
      <comment>I dont know exactly what your trying to accomplish, but its wrong :p </comment>
      <created-at type="datetime">2009-03-30T23:40:38+00:00</created-at>
      <id type="integer">153675</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">634</user-id>
      <user-name>Tj Holowaychuk</user-name>
      <user-website>http://vision-media.ca</user-website>
    </refactor>
    <refactor>
      <code>class Item
  def raw_tag_list; "one, two, three, four, five"; end
  def public_tags; [&lt;#Tag name=two&gt;, &lt;#Tag name=five&gt;, &lt;#Tag name=one&gt;, &lt;#Tag name=four&gt;, &lt;#Tag name=three&gt;]; end

  def tags
    return Array.new if raw_tag_list.nil?

    # Get the raw tag list, split, squish (removed whitespace), and add each to raw_tag_array
    # Make sure we skip if the array already has that tag name (remove any duplicates that occur)
    raw_tag_array = Array.new
    raw_tag_list.split(',').each do |raw_tag|
      next if raw_tag_array.include?(raw_tag.squish)
      raw_tag_array &lt;&lt; raw_tag.squish
    end

    tags = Array.new

    # grab all the tag objects
    tags_out_of_order = public_tags
    if tags_out_of_order.size &gt; 0
      # resort them to match raw_tag_list order
      tags = tags_out_of_order.sort { |a, b| raw_tag_array.index(a.name).to_i &lt;=&gt; raw_tag_array.index(b.name).to_i }  ### &lt;-----
    end

    tags
  end
end
</code>
      <code-id type="integer">807</code-id>
      <comment>Thanks for trying. I ended up going with the following or now. Note the sort replacing 5 lines. The idea is to take an unordered sql query result from Rails, and order it according to a comma separated string.</comment>
      <created-at type="datetime">2009-03-30T23:46:16+00:00</created-at>
      <id type="integer">153676</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">1425</user-id>
      <user-name>k776</user-name>
      <user-website>http://k776.blogspot.com</user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>(credits to k1mmeh at http://snippets.dzone.com/posts/show/6608 for the one line optimization)</comment>
      <created-at type="datetime">2009-03-30T23:47:17+00:00</created-at>
      <id type="integer">153677</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">1425</user-id>
      <user-name>k776</user-name>
      <user-website>http://k776.blogspot.com</user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>still pretty messy IMO</comment>
      <created-at type="datetime">2009-03-31T00:12:59+00:00</created-at>
      <id type="integer">153681</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">634</user-id>
      <user-name>Tj Holowaychuk</user-name>
      <user-website>http://vision-media.ca</user-website>
    </refactor>
    <refactor>
      <code>class Item
  def raw_tag_list; "one, two, three, four, five"; end
  def public_tags; [&lt;#Tag name=two&gt;, &lt;#Tag name=five&gt;, &lt;#Tag name=one&gt;, &lt;#Tag name=four&gt;, &lt;#Tag name=three&gt;]; end

  def tags
    return Array.new if raw_tag_list.blank?
    raw_tag_array = raw_tag_list.squish.split(/\s?,\s?/).uniq
    tags = public_tags
    tags.sort! { |a, b| raw_tag_array.index(a.name).to_i &lt;=&gt; raw_tag_array.index(b.name).to_i } if tags.size &gt; 0
    tags
  end
end
</code>
      <code-id type="integer">807</code-id>
      <comment>Got it down to this. Can you do better?</comment>
      <created-at type="datetime">2009-03-31T06:41:01+00:00</created-at>
      <id type="integer">153714</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">1425</user-id>
      <user-name>k776</user-name>
      <user-website>http://k776.blogspot.com</user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>Just seems like a really hackish thing to do even having hardcoded orders like that, and sorting like that. Maybe consider using the Comparable mixin or abstract the sorting to a different method. Squishing it all into #tags will just slow it down and prevent you from using that functionality later</comment>
      <created-at type="datetime">2009-03-31T15:15:42+00:00</created-at>
      <id type="integer">153748</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">634</user-id>
      <user-name>Tj Holowaychuk</user-name>
      <user-website>http://vision-media.ca</user-website>
    </refactor>
    <refactor>
      <code>require 'Linguistics'

class Tag &lt; Struct.new(:name)
  NUMBERS = (0..100).inject(Hash.new(1 / 0.0)) do |hash,number|
    hash.merge(Linguistics::EN.numwords(number) =&gt; number)
  end
  
  def to_i
    NUMBERS[name]
  end
  
  def &lt;=&gt;(tag)
    to_i &lt;=&gt; tag.to_i
  end
end

class Item
  def public_tags
    [ Tag.new('eight'), Tag.new('five'), Tag.new('ten'), Tag.new('foo'), Tag.new('one') ]
  end
  
  def tags
    public_tags.sort
  end
end</code>
      <code-id type="integer">807</code-id>
      <comment></comment>
      <created-at type="datetime">2009-04-01T05:07:17+00:00</created-at>
      <id type="integer">153801</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">938</user-id>
      <user-name>Adam</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>Not a huge fan of people using Struct all the time, adding another class to the chain JUST to add one attribute is pretty bad practice IMO, but at least you were able to figure out what he wanted lol </comment>
      <created-at type="datetime">2009-04-01T15:19:44+00:00</created-at>
      <id type="integer">153841</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">634</user-id>
      <user-name>Tj Holowaychuk</user-name>
      <user-website>http://vision-media.ca</user-website>
    </refactor>
    <refactor>
      <code>require 'Linguistics'

Tag = Struct.new(:name).class_eval do
  NUMBERS = (0..100).inject(Hash.new(1 / 0.0)) do |hash,number|
    hash.merge(Linguistics::EN.numwords(number) =&gt; number)
  end
  
  def to_i
    NUMBERS[name]
  end
  
  def &lt;=&gt;(tag)
    to_i &lt;=&gt; tag.to_i
  end

  self
end

class Item
  def public_tags
    [ Tag.new('eight'), Tag.new('five'), Tag.new('ten'), Tag.new('foo'), Tag.new('one') ]
  end
  
  def tags
    public_tags.sort
  end
end</code>
      <code-id type="integer">807</code-id>
      <comment>Refactored to eliminate the inheritance because Tj doesn't like it extra classes. ;)</comment>
      <created-at type="datetime">2009-04-01T15:39:21+00:00</created-at>
      <id type="integer">153844</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">938</user-id>
      <user-name>Adam</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>Haha :P sorry just seems really needless, thats the reason for the attr_* methods</comment>
      <created-at type="datetime">2009-04-01T16:23:23+00:00</created-at>
      <id type="integer">153847</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">634</user-id>
      <user-name>Tj Holowaychuk</user-name>
      <user-website>http://vision-media.ca</user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>I like to make extensive use of Struct on refactormycode because it hides boring implementation details, letting the reader focus on the actual refactoring.</comment>
      <created-at type="datetime">2009-04-01T16:31:26+00:00</created-at>
      <id type="integer">153848</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">938</user-id>
      <user-name>Adam</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">807</code-id>
      <comment>True good point, ive just seen it lots in production code as well with huge arrays of symbols looking all nasty</comment>
      <created-at type="datetime">2009-04-01T17:47:40+00:00</created-at>
      <id type="integer">153857</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Tag ordering code</title>
      <user-id type="integer">634</user-id>
      <user-name>Tj Holowaychuk</user-name>
      <user-website>http://vision-media.ca</user-website>
    </refactor>
  </refactors>
</code>
