Using Ruby::Set, now that we can

I’ve been experimenting with using Set.new and was just wondering what others had experienced…

here’s one example where i’ve used it…

# my namespace
module JcB
  # plugin namespace
  module UniqueLayerColors
    extend self
    def run
      model = Sketchup.active_model
      layers = model.layers
      # Hashing color => [array of layers] so we know which need fixing
      layer_color_hash = Hash.new { |hash, key| hash[key] = [] }
      layers.each do |l|
        lc = l.color.to_a
        layer_color_hash[lc] << l
      end
      # find whats needed
      needed = layers.length - layer_color_hash.length
      # Set is a unique array with 'hash' fast lookup
      @new_cols = Set.new
      # make an array once, I capped the colors to avoid very dark/light
      col_ary = [*40..200]
      # take advantage of Set lookup speed and uniqueness
      until @new_cols.length == needed
        # can't tell which is faster rand(range) or ary.sample, this gave me nicer colors??
        # Set swallows any duplicates so no need for .uniq testing
        @new_cols.add([col_ary.sample, col_ary.sample, col_ary.sample, 255])
      end
      # wrap in single undo
      model.start_operation('unique layer colors')
      layer_color_hash.each_pair do |_k, ary|
        al = ary.length
        # skip unique colors
        next unless al > 1
        # puts 'color' + k.to_s + ' was used by ' + al.to_s + ' layers'
        # then process duplicates in block
        ary.each do |layer|
          # skip the first of mutiples as it will end up being unique...
          next if layer == ary[0]
          # assign a new color
          nc = @new_cols.entries.sample
          # puts '  changed one to ' + nc.to_s
          layer.color = nc
          # then remove from the list [bottles, beer ,wall, etc...]
          @new_cols.delete(nc)
        end
      end
      model.commit_operation
    end
  end
end

#  JcB::UniqueLayerColors.run

thoughts and comment welcomed…

john