![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#11 | |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Quote:
>>> zip(a, b, c...) [(a[0], b[0], c[0] ...), (a[1], b[1], c[1] ...), ...] >>> zip([1, 2, 3], ['a', 'b', 'c']) [(1, 'a'), (2, 'b'), (3, 'c')] |
|
|
|
|
|
|
#12 | |
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
Quote:
I was working the same approach, but with a generator; not nearly as clean, at least to this point. Thanks for your contributions. The exercise here was not to get the job done, but to develop a Pythonic mental slant on problem solving. Older solutions tend to invade and beg for mere transalation. I'm not sure what the relative efficiencies are, but I intend to apply this transform over thousands to millions of items.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers |
|
|
|
|
|
|
#13 | |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Quote:
def xflatten(seq):
for x in seq:
if type(x) is list:
for y in flatten(x):
yield y
else:
yield xfrom itertools import izip a = sum(x * y for x, y in izip(xflatten(grid), xflatten(map))) As an aside, range is not a good function to use for long for-loops, because it constructs a new list each time it's called. The xrange function doesn't have this problem, using a generator approach instead. |
|
|
|
|
|
|
#14 | |
|
Expert Programmer
|
Quote:
|
|
|
|
|
|
|
#15 | |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Quote:
On the other hand, ravel returns an array, which has obvious disadvantages over a generator-based approach for dealing with large volumes of data. Do you know if there's a generator in the Numeric module that does the equivalent to ravel? |
|
|
|
|
|
|
#16 | ||
|
Expert Programmer
|
Quote:
Quote:
|
||
|
|
|
|
|
#17 | |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Quote:
a = sum(grid[i][j] * map[i][j] for j in range(3) for i in range(3)) Or you could abstract the zips and flattens into a further function, for something more readable: def combine(seqs):
return zip(map(flatten, seqs))
a = sum(x * y for x, y in combine(grid, mymap))That said, once you have the flatten and combine functions, you can apply them to other parts of your program. Even factor them off into a library of their own. So saying they take up more lines assumes that they're only going to be used once ![]() Just to satisfy my curiousity, however, I'll run some efficiency tests on the various methods and report back on my findings. |
|
|
|
|
|
|
#18 |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Here's the test code I used:
from itertools import izip
def xflatten(seq):
for x in seq:
if type(x) is list:
for y in xflatten(x):
yield y
else:
yield x
def flatten_test((a, b)):
return sum(x * y for x, y in izip(xflatten(a), xflatten(b)))
def comprehension_test((a, b)):
return sum(a[i][j] * b[i][j] for j in xrange(len(a))
for i in xrange(len(a)))
def traditional_test((a, b)):
sum = 0
for i in xrange(len(a)):
for j in xrange(len(b)):
sum += a[i][j] * b[i][j]
return sumAnd here are the results for the time taken to parse two 1000x1000 lists (in seconds). traditional_test: 0.463695049286 comprehension_test: 0.620153903961 flatten_test: 1.59923195839 However, the results didn't change when I ran them again, so it appears as if using generators and the sum function is around 50% slower than doing it via for loops. I can't hazard a guess where the extra CPU time is vanishing to. Most curious. The flatten_test performed worse than I'd have thought, but considering the number of functions involved, a 300% slowdown is not unduly expected. For kicks, I introduced psyco into the mix. Predictably, it worked better with the most basic approach: traditional_test: 0.0489661693573 comprehension_test: 0.831726789474 flatten_test: 2.478703022 I tried comparing it against a C program that did the same thing, and I got: c_test: 0.026326 |
|
|
|
|
|
#19 |
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
As you probably picked up on, I'm writing this for the Python and not for the functionality. I probably picked the wrong old code for the purpose. I wrote an image analyzer, in C++, a couple of years ago. I wrote all my own classes even though there were some available in the Windows API. For this exercise, I'm using Python and wxWidgets. Not all wxWidget functionality is available in the Python port. For one thing, not all image constructors are available, and for another, there is no direct access to the image data. Access to the data is via sub image, which fits well with the use of a Sobel grid. The result of the gradient approximation cannot be stuffed directly into an output image, however, but requires construction from a flattened collection of pixels. This also requires conversion between character/numeric values for the pixels. It is indeed slow with the image access mixed in with the processing. At this point I'm considering writing my own image class in order to gain direct access to the data. This thread is very helpful and interesting. I'll have to look up psyco.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers |
|
|
|
|
|
#20 | |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Quote:
try:
from psyco import proxy as psyco
except ImportError:
def psyco(func): return func
@psyco
def foobar():
... |
|
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|