Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
1  
Welcome to codereview! As it is, your question is off-topic because the code is broken. Didn't you mean latlon instead of coords ? – Dex' ter Nov 7 at 16:28
    
More, what version of Python would you like to be used when somebody will review your question ? – Dex' ter Nov 7 at 16:32
    
@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):. – Mathias Ettinger Nov 7 at 16:54

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)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.