How to allow iteration over a collection that can be enumerated in multiple ways?

I thought of a 3rd way, but I don’t know if its too clever.

Basically, I can write one method, that takes a cond block as its
argument, and returns a class which defines “each” in terms of that
condition, and includes enumerable. Now I only have to write two
methods, and I can let Enumerable do the heavy lifting for me. Or is
that too clever/confusing?

Cheers,
Sam

Quoteing sroberts@uniserve.com, on Mon, Mar 31, 2003 at 01:19:59PM +0900:

···

Kind of a general question.

If I have a container of objects, and people might want to iterate over
particular sub-sets of those objects (all fields in a particular group,
all fields with a particular title, etc.) I see two ways of doing this:

1 - I define an iterator, and yield to their callback:

def each_by_group(group)
… for all matches
yield(match)
end

2 - I create an array of all the things I would call yield with, and
return it:

def array_of_group(group)
Array.new(all matches…)
end

Pros and cons:

1 is MUCH more efficient for large numbers of objects. With 2 I have to
iterate over my internal array, collecting the objects for which the
condition is true into a new array, and return it, potentially for the
caller to use it temporarily, and then discard it to the GCer.

But…

if I do it myself, I feel like I’m going to replicate, eventually, all
the methods in Enumerable for each order type that I can forsee, so why
not just return an array, and let the caller deal with it using the
Array methods they should already know?

What do other people do?

This seems like a general problem when you have a collection when there
are multiple useful views, and subsets of that collection. My particular
application is vCard decoding.

Thanks,
Sam