1

I have an array of strings:

["username", "String", "password", "String"]

And I want to convert this array to a list of Field objects:

class Field
    attr_reader :name, :type
    def initialize(name, type)
        @name = name
        @type = type
    end
end

So I need to map "username", "String" => Field.new("username", "String") and so on. The length of the array will always be a multiple of two.

Does anyone know if this is possible using a map style method call?

3 Answers 3

4

A bracketed Hash call does exactly what you need. Given

a = ["username", "String", "password", "String"]

Then:

fields = Hash[*a].map { |name, type| Field.new name, type }
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Magnar, an interesting solution that I didn't know existed. I'm going to go with sepp2k's answer as it is more generic. As far as I can see this will only handle the case where there is two object mapping to one, or am I wrong? Could you map say four strings to one object using this method?
The Hash-bracket constructor creates a hash of key=>value pairs out of every other value in the array. So it's perfect for your example, but no, it won't work for larger constructors.
2

1.8.6:

require 'enumerator'
result = []
arr = ["username", "String", "password", "String"]
arr.each_slice(2) {|name, type| result << Field.new(name, type) }

Or Magnar's solution which is a bit shorter.

For 1.8.7+ you can do:

arr.each_slice(2).map {|name, type| Field.new(name, type) }

1 Comment

Excellent that's what I'm looking for. I'm choosing this as the answer as it is more scalable that the Hash method for mapping multiple items to an object.
2

Take a look at each_slice. It should do what you need.

4 Comments

1.9 only, FWIW. Too bad there isn't a map_slice, which is what he's really after.
Maybe 1.8.7 too, I'm not sure.
each_slice is in 1.8.6 too, if you require 'enumerator' (stdlib)
It's 1.8.6. Definitely not 1.9, the docs I linked are for 1.8.7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.