# Can map/collect return fewer values than are found in the ta

**URL:** <https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881>\
**Category:** Ruby\
**Created:** [February 9, 2006, 2:18am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881 "2006-02-09T02:18:54Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 2:18am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/1 "2006-02-09T02:18:54Z")

</div>

Is there a way for collect to return fewer items than the enumerable the  
collect is running on? It looks to me like  
map/collect will return at least one value for each item in the array –  
I’ve seen examples of how to return more items, but  
not less.

Is there a way to do this more succinctly:

VOWELS = %w{a e i o u}  
items = %w{ a b c d e f g h i}  
new\_items = []  
items.each do |item|  
new\_items \<\< item unless VOWELS.include(item)  
end  
new\_items

map/collect in ruby seems very similar to map in perl except that in  
perl  
the block can return zero or more elements. Is there an method in ruby  
that  
is similar to perl’s map?

Thanks,

-Kelly

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 2:32am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/2 "2006-02-09T02:32:50Z")

</div>

On Feb 8, 2006, at 8:18 PM, Kelly Dwight F. wrote:

> VOWELS = %w{a e i o u}  
> ruby that  
> is similar to perl’s map?
> 
> Thanks,
> 
> -Kelly

new\_items = items.reject { |item| VOWELS.include?(item) }

or

new\_items = items.select { |item| true unless VOWELS.include?(item) }

or

new\_items = items.inject([]) { |list, item| list \<\< item unless  
VOWELS.include?(item); list }

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 2:38am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/3 "2006-02-09T02:38:11Z")

</div>

On Thu, Feb 09, 2006 at 10:18:46AM +0900, Kelly Dwight F. wrote:

> new\_items = []  
> items.each do |item|  
> new\_items \<\< item unless VOWELS.include(item)  
> end  
> new\_items
> 
> map/collect in ruby seems very similar to map in perl except that in perl  
> the block can return zero or more elements. Is there an method in ruby that  
> is similar to perl’s map?

Looks like you want Arry#select. In fact, take a look at the docs 😉

## ----------------------------------------------------------- Array#select array.select {|item| block } -\> an\_array

```
 Invokes the block passing in successive elements from _array_,
 returning an array containing those elements for which the block
 returns a true value (equivalent to +Enumerable#select+).

    a = %w{ a b c d e f }
    a.select {|v| v =~ /[aeiou]/} #=> ["a", "e"]

```

marcel

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 2:38am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/4 "2006-02-09T02:38:46Z")

</div>

items.inject([]){|a,i| a \<\< i unless VOWELS.include?(i); a}

Kent.

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 6:13am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/5 "2006-02-09T06:13:07Z")

</div>

Thanks much everyone. I think the combo of map with compact is what I  
needed.

-Kelly

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 10:13am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/6 "2006-02-09T10:13:30Z")

</div>

Logan C. wrote:

> new\_items = items.select { |item| true unless VOWELS.include?(item) }

new\_items = items.select { |item| not VOWELS.include?(item) }

```
robert
```

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 3:10am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/7 "2006-02-09T03:10:51Z")

</div>

The difference seems to be that Ruby’s interpretation of map seems to be  
stricter than Perl’s, e.g. for one item in the original Array, there’s  
exactly one corresponding item in the result.

If you want a method with the behaviour similar to Perl’s, you could do:

```
class Array
	def pl_map(&block)
		map(&block).compact.flatten
	end
end

new_items = items.pl_map { | item | item if VOWELS.include(item) }

```

David V.

DÅ?a Å tvrtok 09 FebruÃ¡r 2006 02:18 Kelly Dwight F. napÃ­sal:

---

<div class="post-metadata">

**Author:** ![aseldo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e95f7d/32.png) [@aseldo](https://www.ruby-forum.com/u/aseldo)\
**Post date:** [February 9, 2006, 10:28am UTC](https://www.ruby-forum.com/t/can-map-collect-return-fewer-values-than-are-found-in-the-ta/64881/8 "2006-02-09T10:28:30Z")

</div>

On 2006-02-09, Kelly Dwight F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Is there a way for collect to return fewer items than the enumerable  
> the collect is running on?

Strictly speaking, no (AFAIK), but it’s easy to fake it. Use  
Array#collect with a block that returns nil when you don’t want an  
element, then Array#compact the result.

Similarly, to get the effect of a block returning multiple values to  
Array#collect, just have the block return an Array and then  
Array#flatten the result.

Cheers,

Jeremy H.
