efficent test for array with only one value?

K

Kyler Laird

I'm trying to discover if there's an efficient way to determine
if all of the values of a Numeric array are the same. In C, I
would search from the second value, checking each against the
first value. The first one that doesn't match would trigger a
False return value. If the loop completes, True would be
returned.

Looking through array functions, I'm not finding anything like
that. I'm imagining that there should be something like an
equal function (Is that Lisp I'm recalling?) that performs
a[0,0] == a[0,1] == a[0,2] == ...
and returns False as soon as it is known. I don't see that.

I can, of course, iterate through all of the values, but it
seems like there should be an efficient built-in function to do
it.

Thank you.

--kyler
 
R

Robert Kern

Kyler said:
I'm trying to discover if there's an efficient way to determine
if all of the values of a Numeric array are the same. In C, I
would search from the second value, checking each against the
first value. The first one that doesn't match would trigger a
False return value. If the loop completes, True would be
returned.

Looking through array functions, I'm not finding anything like
that. I'm imagining that there should be something like an
equal function (Is that Lisp I'm recalling?) that performs
a[0,0] == a[0,1] == a[0,2] == ...
and returns False as soon as it is known. I don't see that.

I can, of course, iterate through all of the values, but it
seems like there should be an efficient built-in function to do
it.

Python 2.3.3 (#1, Dec 28 2003, 00:16:29)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from Numeric import *
>>> a = ones((3,5))
>>> equal.reduce(a.flat) 1
>>> a[0,3] = 0
>>> equal.reduce(a.flat) 0
>>>

Ufuncs are wonderful things.
Thank you.

--kyler


--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
K

Kyler Laird

Robert Kern said:
from Numeric import *
a = ones((3,5))
equal.reduce(a.flat) 1
a[0,3] = 0
equal.reduce(a.flat) 0
Ufuncs are wonderful things.

Yeah, but they also don't work for this. First, I'm guessing that reduce
will not stop immediately when equal encounters a False. (It doesn't do
"and".)

Also, it just plain doesn't work.
>>> import Numeric
>>> a = Numeric.zeros((3,5))
>>> Numeric.equal.reduce(a.flat)
0
>>> Numeric.equal.reduce([0,0,0,0,0,0,1])
1

--kyler
 
R

Robert Kern

Kyler said:
from Numeric import *
a = ones((3,5))
equal.reduce(a.flat)
1

a[0,3] = 0
equal.reduce(a.flat)
0

Ufuncs are wonderful things.


Yeah, but they also don't work for this. First, I'm guessing that reduce
will not stop immediately when equal encounters a False. (It doesn't do
"and".)

Also, it just plain doesn't work.
>>> import Numeric
>>> a = Numeric.zeros((3,5))
>>> Numeric.equal.reduce(a.flat)
0
>>> Numeric.equal.reduce([0,0,0,0,0,0,1])
1

Yeah, I'm sorry. I had a brainfart (one of several today, alas). The
reduce method is completely the wrong thing to use since it uses the
*result* of the last comparison as the first argument for the following
comparison.

However, alltrue(a.flat == a.flat[0]) will work but won't short-circuit.
Fast, though, if the array isn't huge.

--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
S

Scott David Daniels

Kyler said:
... I'm guessing that reduce
will not stop immediately when equal encounters a False.

If the early stop is what you want, how about:
if vector:
d = {}
d[vector[0]] = 0
try:
for el in vector:
d[el]
except KeyError:
return False
return True

-Scott David Daniels
(e-mail address removed)
 
K

Kyler Laird

Robert Kern said:
However, alltrue(a.flat == a.flat[0]) will work but won't short-circuit.

How did I miss that?! Yes, that's the kind of operation I sought.
I'm surprised that it doesn't short-circuit. It *should*, right?

It's a shame that it only works along a single axis. The use of
"flat" is a problem for me. I'm looking at sections of an image
(building a quadtree) so the arrays I'm checking are not contiguous.
I think that means I have to resort to something ugly like this.
Numeric.alltrue(Numeric.alltrue(a == a[0,0]))
That eliminates many opportunities for short-circuiting.

I can also flatten the array using reshape() before checking it. I
assume that also means a lot of possibly unnecessary operations.
(Does reshape() return a copy of the array or just an array with
the original data and a new shape?)
Fast, though, if the array isn't huge.

Indeed, I think I'll use it. I can always write a clean short-
circuiting C version later.

Thank you!

--kyler
 
D

David M. Cooke

At some point said:
Robert Kern said:
However, alltrue(a.flat == a.flat[0]) will work but won't short-circuit.

How did I miss that?! Yes, that's the kind of operation I sought.
I'm surprised that it doesn't short-circuit. It *should*, right?

It's a shame that it only works along a single axis. The use of
"flat" is a problem for me. I'm looking at sections of an image
(building a quadtree) so the arrays I'm checking are not contiguous.
I think that means I have to resort to something ugly like this.
Numeric.alltrue(Numeric.alltrue(a == a[0,0]))
That eliminates many opportunities for short-circuiting.

I can also flatten the array using reshape() before checking it. I
assume that also means a lot of possibly unnecessary operations.
(Does reshape() return a copy of the array or just an array with
the original data and a new shape?)

In general, use ravel() instead of .flat.
ravel() is a simple wrapper around reshape(), which will make a
contiguous only if necessary. .flat will fail for non-contiguous arrays
(like views into another array).
 

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
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top