0
\$\begingroup\$

I have two lists of coordinates,

lat = [-23.23, -44.23, -12.23]
lon = [-21.23, -14.23, -62.23]

and I generate a tuple of lat long pairs with zip:

latlon = zip(lat, lon)

and that gives the expected result. Now there is a very common pattern of generating lines with the points. It is common to do something like

 line_coords = []
 for i in xrange(len(coords)-1):
 line_coords.append([tuple(coords[i]), tuple(coords[i+1])])

so the result is now a list of tuples, each tuple an list of beginning and end of a line:

line_coords
[[(-23.23, -21.23), (-44.23, -14.23)], [(-44.23, -14.23), (-12.23, -62.23)] ]

and it get worse if the line needs to come back to the beginning. This looks like an anti-pattern. Is there a name for this pattern and a more elegant way to do it?

Peilonrayz
44.4k7 gold badges80 silver badges157 bronze badges
asked Nov 7, 2016 at 16:21
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to codereview! As it is, your question is off-topic because the code is broken. Didn't you mean latlon instead of coords ? \$\endgroup\$ Commented Nov 7, 2016 at 16:28
  • \$\begingroup\$ More, what version of Python would you like to be used when somebody will review your question ? \$\endgroup\$ Commented Nov 7, 2016 at 16:32
  • \$\begingroup\$ @Dex'ter There is nothing that requires the two snippets to be that related. For what it's worth, latlon could be passed to a function defined along the lines of def whatever(coords):. \$\endgroup\$ Commented Nov 7, 2016 at 16:54

1 Answer 1

3
\$\begingroup\$

When it comes to iteration in Python, there is often an itertools recipe or function that come close to the needs.

Here, I’m thinking about pairwise which is defined as:

def pairwise(iterable):
 "s -> (s0,s1), (s1,s2), (s2, s3), ..."
 a, b = itertools.tee(iterable)
 next(b, None)
 return itertools.izip(a, b)

If you’re interested in cycling back to the beginnig, you should consider itertools.cycle too:

def get_line_coordinates(iterable, close=False):
 """s -> (s0,s1), (s1,s2), (s2, s3), ...
 ends with (sN, s0) if close is True else (sN-1, sN)
 """
 a, b = itertools.tee(iterable)
 if close:
 b = itertools.cycle(b)
 next(b, None)
 return itertools.izip(a, b)

Lastly, itertools.izip_longest will let you fill that last value by consumming less memory than cycle:

def get_line_coordinates(iterable, close=False):
 """s -> (s0,s1), (s1,s2), (s2, s3), ...
 ends with (sN, s0) if close is True else (sN-1, sN)
 """
 a, b = itertools.tee(iterable)
 beginning = next(b, None)
 if close:
 return itertools.izip_longest(a, b, fillvalue=beginning)
 return itertools.izip(a, b)
answered Nov 7, 2016 at 16:44
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.