# How to collect over two arrays then look back to one?

**URL:** <https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571>\
**Category:** Ruby\
**Created:** [September 13, 2006, 6:11pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571 "2006-09-13T18:11:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 13, 2006, 6:11pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/1 "2006-09-13T18:11:47Z")

</div>

I am reading Ruby for Rails and Ruby Cookbock and delighted by the  
Array#find\_all and Enumerable#collect methods. I’m wondering what the  
idiomatic way to do the following is?

Two parallel arrays A, B . For each element n of A for which f(An) is  
true,  
is g(B[n-3:n+3]) true? Where B[n-3:n+3] refers to seven elements of B  
whose  
position is centered over An’ position.

Can the block inside Enumerable#collect know it’s position inside the  
Enumerable? Can one collect two parallel arrays?

## Peter

* * *

The information contained in and accompanying this communication is  
strictly  
confidential and intended solely for the use of the intended  
recipient(s).  
If you have received it by mistake please let us know by reply and then  
delete it from your system; you should not copy the message or disclose  
its  
content to anyone.  
MarketAxess reserves the right to monitor the content of emails sent to  
or  
from its systems.  
Any comments or statements made are not necessarily those of  
MarketAxess.  
For more information, please visit [www.marketaxess.com](http://www.marketaxess.com). MarketAxess  
Europe  
Limited is regulated in the UK by the FSA, registered in England no.  
4017610, registered office at 71 Fenchurch Street, London, EC3M 4BS.  
Telephone (020) 7709 3100.  
MarketAxess Corporation is regulated in the USA by the SEC and the NASD,  
incorporated in Delaware, executive offices at 140 Broadway, New York,  
NY  
10005. Telephone (1) 212 813 6000.

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 13, 2006, 7:11pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/2 "2006-09-13T19:11:56Z")

</div>

On 9/13/06, Peter B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Can the block inside Enumerable#collect know it’s position inside the  
> Enumerable? Can one collect two parallel arrays?
> 
> Peter

Hmm this seems interestingly complicated - or I am just dully stupid;)

Well here is what I came up with:

a = [\*1…20]  
b = a.map{ |e| “Line #{e}” }

def ranges a, b, n, &block

### The following is what you were asking for 😉

```
b.values_at(*(0..a.length-1).zip(a).map{|e| block.call(e.last) ?

```

e.first: nil}.  
compact.map{|i|  
[\*(i-n)…(i+n)]}.flatten.uniq.reject{|i|i\<0}).compact

end

p ranges(a,b,1) { |e| (e%3).zero? }  
p ranges(a,b,2) { |e| (e%3).zero? }  
p ranges(a,b,1) { |e| (e%5).zero? }  
p ranges(a,b,2) { |e| (e%5).zero? }

HTH  
Robert

PS:  
Golfers cut it down 😉

R

–  
Deux choses sont infinies : l’univers et la bÃªtise humaine ; en ce qui  
concerne l’univers, je n’en ai pas acquis la certitude absolue.

- Albert Einstein

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 13, 2006, 7:13pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/3 "2006-09-13T19:13:56Z")

</div>

I think…

a.values\_at(\*(0…a.size).to\_a.select {|i| f(a[i]) &&  
g([i-3,0].max…[i+3,a.size-1].min)})

Ruby seems a little verbose on this one.

-j

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 13, 2006, 10:16pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/4 "2006-09-13T22:16:25Z")

</div>

On 9/13/06, Jason N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I think…
> 
> a.values\_at(\*(0…a.size).to\_a.select {|i| f(a[i]) && g([i-3,0].max…[i+3, a.size-1].min)})

I am afraid this does not what you want, select returns i’s not the  
value of  
the block  
you had some great ideas I have stolen below though 🙂  
I’ll try to fix your interpretation, ah I see you think he just wants  
the  
indicies, so your solution is (almost) great, you can use [\*0…a.size]  
but  
you might have a problem with f(nil) so use  
[_0…a.size-1]  
OP also stated he wanted g(b[something]) not g(something) it is a riddle  
an alternative might be  
b.values\_at([0…a.size-1].select{|i|f a[i]}.map{|i|  
g(b.values\_at([_(i-n)…(i+n)].reject  
etc. etc.

Ruby seems a little verbose on this one.

> -j

I still think OP thaught g to be something abstract so I would write

def ranges a, b, n, &block

### The following is what you were asking for 😉

```
b.values_at(
*(0..a.length-1).select{|i| block.call(a[i]) }.map{|i| 

```

[\*(i-n)…(i+n)]  
}.  
flatten.uniq.reject{|i|i\<0}).compact

end

thanks to your ideas letting me see my stupid mistakes…

Robert

Peter B. wrote:

> > Can the block inside Enumerable#collect know it’s position inside the  
> > recipient(s).  
> > Europe

–  
Deux choses sont infinies : l’univers et la bÃªtise humaine ; en ce qui  
concerne l’univers, je n’en ai pas acquis la certitude absolue.

- Albert Einstein

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 13, 2006, 11:20pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/5 "2006-09-13T23:20:33Z")

</div>

Peter B. wrote:

> I am reading Ruby for Rails and Ruby Cookbock and delighted by the  
> Array#find\_all and Enumerable#collect methods. I’m wondering what the  
> idiomatic way to do the following is?
> 
> Two parallel arrays A, B . For each element n of A for which f(An) is true,  
> is g(B[n-3:n+3]) true? Where B[n-3:n+3] refers to seven elements of B whose  
> position is centered over An’ position.
> 
> Can the block inside Enumerable#collect know it’s position inside the  
> Enumerable? Can one collect two parallel arrays?

a = Array.new(12) {|i| i_i}  
b = Array.new(12) {|i| i_3}  
def f(n)  
1 == n % 2  
end  
def g(a)  
return false if a.size != 7  
0 == a.inject{|p,n| p\*n}/a.inject{|s,n| s+n} % 4  
end  
result = []  
a.each\_with\_index{ |e,i|  
result \<\< (f(e) && g( b[i-3 … i+3] ))  
}

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 13, 2006, 11:22pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/6 "2006-09-13T23:22:33Z")

</div>

Peter B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> I am reading Ruby for Rails and Ruby Cookbock and delighted by the  
> Array#find\_all and Enumerable#collect methods. I’m wondering what the  
> idiomatic way to do the following is?

Kind of. But first I’m going to re-arrange your email to answer more  
didactically. 🙂

> Can the block inside Enumerable#collect know it’s position inside the  
> Enumerable?

Enumerable::Enumerator – require ‘enumerator’ – can help you out with  
this.  
It lets you create an Enumerable object which can call any ‘each’-like  
method  
of any other object. You can in turn call the ‘collect’ method of the  
Enumerator object. So:

```
array.to_enum(:each_with_index).collect { |value, index| ... }

```

(Using :each\_with\_index is a common enough case that Enumerator also  
adds  
#enum\_with\_index to Enumerable.)

> Can one collect two parallel arrays?

In several ways… The most basic is the Enumerable#zip method:

```
(0..3).zip(('a'..'d')) # => [[0, "a"], [1, "b"], [2, "c"], [3, "d"]]

```

It returns a new array mapping each element of the receiving Enumerable  
to the  
corresponding elements of the Enumerables passed as arguments.

> Two parallel arrays A, B . For each element n of A for which f(An) is true,  
> is g(B[n-3:n+3]) true? Where B[n-3:n+3] refers to seven elements of B whose  
> position is centered over An’ position.

Enumerable#inject is the most idiomatic way to perform most Enumerable  
iteration not directly supported by other methods. If I understand you  
properly, in this case you probably want something like:

```
a.enum_with_index.inject([]) do |result, (v, n)|
  result << (f(v) ? g(b[n-3..n+3]) : false)
end

```

Hope this helps!

-Marshall

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 15, 2006, 11:15am UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/7 "2006-09-15T11:15:31Z")

</div>

removed\_email\_address@domain.invalid writes:

> To answer the first question: no. You are free to join Citizens for  
> map\_with\_index, of which I am the founder and president 🙂

What about Citizens Who Are Happy With enum\_with\_index.map ? I think  
they  
have a thing-or-two to say on this issue…

-Marshall

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 15, 2006, 10:45am UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/8 "2006-09-15T10:45:30Z")

</div>

Hi –

On Thu, 14 Sep 2006, Peter B. wrote:

> I am reading Ruby for Rails and Ruby Cookbock and delighted by the  
> Array#find\_all and Enumerable#collect methods. I’m wondering what the  
> idiomatic way to do the following is?
> 
> Two parallel arrays A, B . For each element n of A for which f(An) is true,  
> is g(B[n-3:n+3]) true? Where B[n-3:n+3] refers to seven elements of B whose  
> position is centered over An’ position.
> 
> Can the block inside Enumerable#collect know it’s position inside the  
> Enumerable? Can one collect two parallel arrays?

To answer the first question: no. You are free to join Citizens for  
map\_with\_index, of which I am the founder and president 🙂

David

---

<div class="post-metadata">

**Author:** ![bodikp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e79b87/32.png) [@bodikp](https://www.ruby-forum.com/u/bodikp)\
**Post date:** [September 15, 2006, 3:16pm UTC](https://www.ruby-forum.com/t/how-to-collect-over-two-arrays-then-look-back-to-one/68571/9 "2006-09-15T15:16:17Z")

</div>

On Fri, Sep 15, 2006 at 06:15:59PM +0900, Marshall T. Vandegrift wrote:

> removed\_email\_address@domain.invalid writes:
> 
> > To answer the first question: no. You are free to join Citizens for  
> > map\_with\_index, of which I am the founder and president 🙂
> 
> What about Citizens Who Are Happy With enum\_with\_index.map ? I think they  
> have a thing-or-two to say on this issue…
> 
> -Marshall

Here, here! Down with the giant collection of methods! Up with  
higher order methods!
