2

I am currently writing a program that takes in the points of multiple circles, stored as tuples (x, y, z) in coor_input, from a csv file and processes them, each circle is identified by the z coordinate, I have managed this but with the use of multiple loops which I want to optimise for speed and neatness. I have tried using

    for zs in coor_input:
        if zs[2] not in z:
            z.append(zs[2])

but that is almost exactly the same as the for loop. I am currently using the code below that works but I am looking for a way to condense it if at all possible?

coor_input is a list of coordinates stored as tuples ((1,2,3), (4,5,6)...)

    #store each circle value of z coordinate
    for ii in range(0, len(coor_input)):
        if coor_input[ii][2] not in z:
            z.append(coor_input[ii][2])

    #each z identifies different circle
    #go through each circle
    for j in range(0, len(z)):
        #reset coordinates
        coordinates = []

        #add coordinates to the circle of they have the 
        #same z coordinate as the circle
        for f in range(0, len(coor_input)):
            if coor_input[f][2] == z[j]:
                #add coordinates of that circle
                coordinates.append(coor_input[f])

        #Process circle

There must be a way to optimise this but I have no clue, any help would be greatly appreciated

3
  • What is the purpose of checking for not in z? Do you want each z-coordinate to appear only once in z? If so, you should make z a set. Commented Jan 16, 2014 at 21:56
  • ofc! I should have seen that, thanks!:) Commented Jan 16, 2014 at 21:59
  • Just confirming you want any circle with a particular z coordinate (ie. pick the first one, ignore the rest)? Commented Jan 16, 2014 at 22:02

3 Answers 3

4

Collect circles in a dictionary, keyed by z coordinate:

from collections import defaultdict

circles = defaultdict(list):

for x, y, z in coor_input:
    circles[z].append((x, y, z))

This uses a collections.defaultdict()object to make materializing a list per z coordinate easier; this is a simple dict subclass and can be used like any normal dictionary.

Now you have a dictionary whose values are lists, one list per z coordinate. This takes one single loop to collect them all. You can then process all circles for a given z coordinate:

for z, coords in circles.iteritems():
    # process circle
    # coords is a list of (x, y, z) coordinates where z is the same

Your code appears to ignore the first-found circle coordinates; if that is intentional, just use coords[1:] to skip the first coordinates found for the given z point.

Sign up to request clarification or add additional context in comments.

2 Comments

Brilliant! so much quicker, exactly what I was looking for thank you!
already have! :D (Note to anyone else wanting to use this in python 3.3 - change iteritems() to items(), does exactly the same thing!)
0

Don't make z a list, but instead a set. Then you get O(1) efficiency:

z = set()
for zs in coor_input:
    z.add(zs[2])

Edited to reduce my stupidity per comment

1 Comment

You don't need the not in z check if you're using a set. x = {1}; x.add(1) works fine and ends with x == {1}.
0

Consider using list comprehension, which can be quite fast. For example, let's say you wanted to process each circle by some function. I'll arbitrarily define one here, but it could be pretty much anything.

def process_circle(circle):
    return math.sqrt(circle[0]^2 + circle[1]^2 + circle[2]^2)

Now we can very quickly create a list of the results of this processing on each circle in coor_input like so:

[ process_circle(c) for c in coor_input ]

Putting it all together into a test program:

import math

coor_input = ( (1,2,3), (4,5,6), (3,9,3), (2,3,6) )

def process_circle(circle):
    return math.sqrt(circle[0]^2 + circle[1]^2 + circle[2]^2)

print [ process_circle(c) for c in coor_input ]

The result is:

[1.4142135623730951, 3.0, 3.872983346207417, 3.605551275463989]

If they absolutely must be processed in order of their third (z) value, you can use this:

print [ process_circle(c) for c in sorted(coor_input, cmp=lambda a,b: cmp(a[2],b[2])) ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.