27 Oct, 2008

Published at 07:46PM

Tagged with extensions, programming, ruby, and tips

This post has 5 comments

Ruby: inject_with_index

Here’s a useful extension:

1
2
3
4
5
6
module Enumerable
  def inject_with_index(injected)
    each_with_index{ |obj, index| injected = yield(injected, obj, index) }
    injected
  end
end

Example usage

This is useful for a number of reasons, one being when you have two separate arrays of related data that you’d like to combine into a single array. For example, I’m pulling in my public github projects in the about section by scraping GitHub’s HTML (using Hpricot).

I’m using inject_with_index to organize the parsed response into a single array, which I can then iterate through and easily output.

1
2
3
4
5
6
7
8
9
10
def github_projects
  # ...

  titles = html / 'div.title b a'
  descriptions = html / 'div.description'

  titles.inject_with_index([]) do |projects, title, index|
    projects << [title, descriptions[index]]
  end
end

And it’s also less worry to cache that single array than trying to keep track of titles and descriptions separately later on. A win-win.

Now, hopefully this doesn’t already exist. I couldn’t find it, but that doesn’t mean I didn’t reinvent the wheel.

Comments

Chris Monday, 27 Oct, 2008 Posted at 08:41PM

I don’t want to burst your bubble, but…

1
2
3
4
5
  # combine two arrays
  titles.zip(descriptions)

  # combine two arrays and make them into a Hash
  Hash[*titles.zip(descriptions).flatten]

Granted, zip isn’t the most obvious method name, but there you go.

Chris Monday, 27 Oct, 2008 Posted at 08:44PM

Also, have you seen this?

Github badge

Ryan Monday, 27 Oct, 2008 Posted at 11:07PM

Ahhhhh, zip. For the Nth time, I should know better!

Yeah, I saw that github badge a while ago, but depending on my mood, I like to be in control of how things are done. In this case, I redid the api/caching stuff to be somewhat generic, so it was easy to add the github stuff with the other things (flickr, delicious, and my portfolio).

Man. Stupid zip. At least I won’t forget it.

Chris Lloyd Wednesday, 30 Mar, 2011 Posted at 11:32PM

For Google prosperity, in Ruby 1.9 you can do this:

1
2
3
4
[1,2,3].each_with_index.inject(0) do |tot, (obj, i)|
   puts "Adding number #{i}"
   tot += obj
end

Phrogz Thursday, 09 Jun, 2011 Posted at 12:14PM

Or in 1.9:

1
2
3
4
[1,2,3].enum_for(:inject,0).with_index do |(sum,n),i|
  puts "Adding number #{i}"
  sum + n
end
Do you have something to say about this post?
Retype the image to the right Spam Hint: Are You Human? Textile Formatting Tips

or

Ryan Heath | Site Management A Ruby on Rails production.

This site is a Formed Function. Formed Function LLC | @formedfunction | Get in Touch