new method(?) collect_by

  • Thread starter Kristof Bastiaensen
  • Start date
K

Kristof Bastiaensen

Hi, I have written a method collect_by.
I am not sure if it already exist, but it is very
usefull. It is a generic version of collect, that
works with any method. Basicly it converts the output
of any block to an Array

class Object
def collect_by(method, *args)
a = []
send(method, *args) { |*o|
a.push(block_given? ?
(yield *o) :
(o.size > 1 ? o : o[0])) }
return a
end
end

Examples:

"a string".collect_by:)each_byte)
=> [97, 32, 115, 116, 114, 105, 110, 103]

3.collect_by:)step, 20, 4)
=>[3, 7, 11, 15, 19]

(3..7).collect_by:)each_with_index)
=> [[3, 0], [4, 1], [5, 2], [6, 3], [7, 4]]

5.collect_by:)times) { rand 100 }
=> [61, 85, 13, 52, 47]

5.collect_by:)times) { |i| i * i }
=> [0, 1, 4, 9, 16]
 
D

Dan Doel

Interesting. I don't think I've ever seen that before.

If you find that useful, perhaps you'll find the following interesting:

class Object
def inject_by(init, method, *args, &blk)
a = init
send(method, *args) do |*o|
a = yield a, o
end
a
end

def collect_by(method, *args, &blk)
inject_by([], method, *args) do |a, o|
a << if blk
blk.call *o
else
o.size > 1 ? o : o[0]
end
end
end
end

My #collect_by and yours does the same thing, plus I made the even more
general #inject_by. :)

I don't know where I'd ever use this, but who knows?

Cheers.

- Dan
 
G

George Ogata

Kristof Bastiaensen said:
Hi, I have written a method collect_by.
I am not sure if it already exist, but it is very
usefull. It is a generic version of collect, that
works with any method. Basicly it converts the output
of any block to an Array

[...]

You might be interested in enumerator.rb in the std lib:

irb(main):001:0> require 'enumerator'
=> true
irb(main):002:0> 'a string'.enum_for:)each_byte).map{|x| x}
=> [97, 32, 115, 116, 114, 105, 110, 103]
irb(main):003:0> 'a string'.enum_for:)each_byte).max
=> 116
irb(main):004:0> 'a string'.enum_for:)each_byte).inject{|x,y| x+y}
=> 792

etc.
 
K

Kristof Bastiaensen

You might be interested in enumerator.rb in the std lib:

irb(main):001:0> require 'enumerator' => true irb(main):002:0> 'a
string'.enum_for:)each_byte).map{|x| x} => [97, 32, 115, 116, 114, 105,
110, 103] irb(main):003:0> 'a string'.enum_for:)each_byte).max => 116
irb(main):004:0> 'a string'.enum_for:)each_byte).inject{|x,y| x+y} =>
792

etc.

Hi,

yes that does exactly what I wanted. I knew it should exist,
but couldn't find it.
I am still using ruby 1.6, so it must be part of 1.8.

Thanks,
Kristof
 
K

Kristof Bastiaensen

Interesting. I don't think I've ever seen that before.

If you find that useful, perhaps you'll find the following interesting:

class Object
def inject_by(init, method, *args, &blk)
a = init
send(method, *args) do |*o|
a = yield a, o
end
a
end

def collect_by(method, *args, &blk)
inject_by([], method, *args) do |a, o|
a << if blk
blk.call *o
else
o.size > 1 ? o : o[0]
end
end
end
end

My #collect_by and yours does the same thing, plus I made the even more
general #inject_by. :)

I don't know where I'd ever use this, but who knows?

Cheers.

- Dan

Hi,
I think it is very useful. I found out a general class is already
implemented in the std lib with enumerator. This way you
can use all the methods of Enumerator.
Some examples:

filling in an Array:

5.enum_for:)times).collect { Array.new(5) }
(maybe shorter: (0..4).collect { Array.new(5) }

string manipulation on bytes:

"a string".enum_for:)each_byte).collect { |b| b + 3 }.join

Greetings,
Kristof
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,824
Members
47,369
Latest member
FTMZ

Latest Threads

Top