# Easy question

**URL:** <https://www.ruby-forum.com/t/easy-question/95667>\
**Category:** Ruby\
**Created:** [June 8, 2006, 3:21pm UTC](https://www.ruby-forum.com/t/easy-question/95667 "2006-06-08T15:21:01Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 3:21pm UTC](https://www.ruby-forum.com/t/easy-question/95667/1 "2006-06-08T15:21:01Z")

</div>

I want to maintain a list of two-dimensional points and store, at list  
level, the min and max values for x and y.

The minx/maxx/miny/maxy should be updated as each point is pushed onto  
the list.

The following works, but it’s probably not leveraging Ruby:

def add\_point( p )  
@points.push§  
if !@minx || @minx \> p.x  
@minx=p.x  
end  
if …

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 3:52pm UTC](https://www.ruby-forum.com/t/easy-question/95667/2 "2006-06-08T15:52:59Z")

</div>

On Jun 8, 2006, at 14:20, Robert M. wrote:

> if !@minx || @minx \> p.x  
> @minx=p.x  
> end  
> if …

There’s not a lot of changes you can make to something as simple as a  
conditional, actually. Even if you improve the aesthetics, there’s  
little practical impact in re-writing simple conditionals.

That said, you can compress each statement into a single line using  
the if/unless as a modifier (like Perl). I tend to prefer ‘unless’  
in this case, but that’s just me.

@minx = p.x unless @minx and p.x \> @minx  
@minx = p.x if !@minx or @minx \> p.x

matthew smillie.

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 3:59pm UTC](https://www.ruby-forum.com/t/easy-question/95667/3 "2006-06-08T15:59:37Z")

</div>

You could have functions that query the points in the system instead  
of keeping track as you add them.

def min\_x  
(@points.min{|a,b| a.x \<=\> b.x}).x  
end

def min\_y  
(@points.min{|a,b| a.y \<=\> b.y}).y  
end

def max\_x  
(@points.max{|a,b| a.x \<=\> b.x}.x  
end

def max\_y  
(@points.min{|a,b| a.y \<=\> b.y}).y  
end

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 3:59pm UTC](https://www.ruby-forum.com/t/easy-question/95667/4 "2006-06-08T15:59:29Z")

</div>

Robert M. wrote:

> def add\_point( p )  
> @points.push§  
> if !@minx || @minx \> p.x  
> @minx=p.x  
> end  
> if …

@points is an array of arrays, right?

def add\_point§  
@points.push§  
@max\_x = @points.inject{|max, cur| cur[0] \> max[0] ? cur : max}[0]  
@min\_x = @points.inject{|min, cur| cur[0] \< min[0] ? cur : max}[0]  
@max\_y = @points.inject{|max, cur| cur[1] \> max[1] ? cur : max}[1]  
@min\_y = @points.inject{|min, cur| cur[1] \< min[1] ? cur : max}[1]  
end

Depending on how often you update the array, and how often you want the  
min/max values, you ought to consider putting each #inject in its own  
method instead:

def max\_x  
@points.inject{|max, cur| cur[0] \> max[0] ? cur : max}[0]  
end

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 4:08pm UTC](https://www.ruby-forum.com/t/easy-question/95667/5 "2006-06-08T16:08:56Z")

</div>

But doesn’t that result in an iteration over the points array every time  
we want to get min/max values?

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 4:05pm UTC](https://www.ruby-forum.com/t/easy-question/95667/6 "2006-06-08T16:05:47Z")

</div>

1. 

@points is an array of point objects

class Point  
:attr\_reader :x, :y  
def initialize( x, y )  
@x, @y=x,y  
end  
end

1. 

With inject, aren’t you iterating over the entire array every time you  
add a new point, such that series.add§ becomes O n^2?

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 4:24pm UTC](https://www.ruby-forum.com/t/easy-question/95667/7 "2006-06-08T16:24:16Z")

</div>

> -----Original Message-----  
> From: Robert M. [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]  
> Sent: Thursday, June 08, 2006 4:06 PM  
> To: ruby-talk ML  
> Subject: Re: Easy question
> 
> But doesn’t that result in an iteration over the points array  
> every time  
> we want to get min/max values?

Yes, which is slow, but also secure. Is there a way to  
remove items from your list? what happens to the minx, etc.  
if you remove the smallest one?

suggestion:

def min\_x  
@minx ||= (@points.min{|a,b| a.x \<=\> b.x}).x  
end

…

def add\_point( p )  
@points.push(p)  
@minx = @maxx = @miny = @maxy = nil  
end

def del\_point( p )  
@points.delete(p)  
@minx = @maxx = @miny = @maxy = nil  
end

cheers

Simon

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 4:44pm UTC](https://www.ruby-forum.com/t/easy-question/95667/8 "2006-06-08T16:44:04Z")

</div>

Robert M. wrote:

> With inject, aren’t you iterating over the entire array every time you  
> add a new point, such that series.add§ becomes O n^2?

Yes, I didn’t see that until after i posted ☹  
I actually did the #(max|min)\_(x|y) thing first, and then just copied  
the code after re-reading your post. My bad.

Robert M. wrote:

> @points is an array of point objects
> 
> class Point  
> :attr\_reader :x, :y  
> def initialize( x, y )  
> @x, @y=x,y  
> end  
> end

def max\_x  
@points.inject{|max, cur| cur.x \> max.x ? cur : max}.x  
end

I’d personally use that approach – but if you’re accessing the method  
often, it’s rather inefficient.

Daniel

---

<div class="post-metadata">

**Author:** ![newbee-robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/dbc845/32.png) [@newbee-robert](https://www.ruby-forum.com/u/newbee-robert)\
**Post date:** [June 8, 2006, 4:27pm UTC](https://www.ruby-forum.com/t/easy-question/95667/9 "2006-06-08T16:27:37Z")

</div>

It does and if that’s a concern due to the number of points then it’s  
probably best to keep track of the min/max then.
