Question: I am trying to replace a component in a legacy system with a Ruby script. One piece of this system accepts a string that contains ASCII '0's and '1's apparently to represent a bitfield of locations. It then converts these location to a string of comma separated 2 two codes (mostly US states).

I have a Ruby method that does this but it doesn't seem like I am doing it the best way Ruby could. Ruby has a ton of ways built in to iterate over and manipulated array and I feel I am not using them to their fullest:

```
# input "0100010010" should return "AZ,PR,WY"
def locations(bits)          
  # Shortened from hundreds for this post. :u? is for locations I have't figured out yet.
  fields = [ :u?, :az, :de, :mi, :ne,    :wy, :u?, :u?, :pr, :u? ] 
  matches = []
  counter = 0
  fields.each { |f|
    case bits[counter]
      when '1' then matches << f
      when '0' then nil
      else raise "Unknown value in location bit field"
    end
    counter += 1
  }
  if matches.include(:u?) then raise "Unknown field bit set"  end
  matches.sort.join(",").upcase
end

```

What would be a better way to do this?

It seems counter to the "Ruby way" to have counter variables floating around. I tried looking at ways to use Array#map, and I could find nothing obvious. I also tried Googling for Ruby Idioms pertaining to Arrays.

Answer: 
Use [`Array#zip`](http://www.ruby-doc.org/core-2.1.1/Array.html#method-i-zip) and [`Array#reduce`](http://ruby-doc.org/core-2.1.0/Enumerable.html#method-i-reduce)

```
bits.split('').zip(fields).reduce([]) do |a, (k, v)| 
  k == '1' ? a << v.to_s.upcase : a
end.sort.join(',')
# => "AZ,PR,WY

```

Explanation:

1) `split` bits into an array of chars:

```
bits.split('')  # => ["0", "1", "0", "0", "0", "1", "0", "0", "1", "0"]

```

2) `zip` both arrays to generate an array of pairs (by position)

```
bits.split('').zip(fields) # => [["0", :u?], ["1", :az], ["0", :de], ["0", :mi], 
# ["0", :ne], ["1", :wy], ["0", :u?], ["0", :u?], ["1", :pr], ["0", :u?]] 

```

3) `reduce` the array taking the desired elements according to the conditions

```
.reduce([]) do |a, (k, v)| 
  k == '1' ? a << v.to_s.upcase : a
end  # => "[AZ,WY,PR]

```

4) `sort` the resulting array and `join` their elements to get the expected string

```
.sort.join(',') # => "AZ,PR,WY"

```
You could combine `each_with_index`, `map` and`compact`:

```
fields.each_with_index.map do |v,i| 
    v if bits[i] == '1' 
end.compact

```

`each_with_index` returns an iterator for each each value and its integer index.

`map` uses the return value of a passed block to yield an output value for each input value. The block returns the value if its corresponding bit is set, and implicitly returns `nil` if it is not. 

`compact` returns a copy of the output array with all of the `nil` values removed.

For more detail see the docs for [Enumerable](http://ruby-doc.org/core-2.1.0/Enumerable.html) and [Array](http://ruby-doc.org/core-2.1.0/Array.html).