简体   繁体   中英

How to store 'yield' generator result in a list in Python 2.7?

I have a code like this:

import math    
nList = [[[0, 0, 0], [3, 2, 1]],\
     [[]],\
     [[1, 1, 12]],\
     [[0, 0, 0], [30000, 40, 3010], [32000, 40500, 7520], [0, 0, 10520]],\
     [[15340, 0, 0], [104300, 0, 3630], [434000, 4434000, 63460]]]

def calculate_length(x1, y1, x2, y2):
    return math.sqrt((x1-x2)**2 + (y1 - y2)**2)

def calculate_time (t1,t2):
    return abs(t1-t2)

def lengths(trace):
    previous_x, previous_y = 0, 0
    for index, point in enumerate(trace):
        if point:
            x, y, t = point
            if index > 0:
                yield calculate_length(x, y, previous_x, previous_y)
            previous_x, previous_y = x, y

How would I store the yield results of calculate_length(x, y, previous_x, previous_y) in a list?

nList has traces in them with each trace having points with 3 elements, [x,y,t] . I need to store the lengths of each trace so that the output generated is:

all_lengths_list=[[3]],[[]],[[]],[[30000.02667],[40509.40138],[51616.37337]],[[88960],[4446240]]]

只需使用list

result = list(lengths(trace))

You don't need those line-continuation backslashes - modern Python is smart enough to figure out that the list definition isn't complete and so it does the line-continuation automatically for you.

Also, there's no need to import the math module just to calculate a square root, you can use the built-in power operator: ** 0.5 .

To get the output you want you need to feed the trace lists in nList to your generator one at a time, capturing the resulting data into lists which are then saved in all_lengths_list . This can be done in a normal for loop, but it's more compact to use a list comprehension, as in the code below. To display the contents of all_lengths_list I use pprint() from the pprint module. It's not that pretty, but it's better than putting it all onto one line. :)

#!/usr/bin/env python

from pprint import pprint

nList = [
    [[0, 0, 0], [3, 2, 1]],
    [[]],
    [[1, 1, 12]],
    [[0, 0, 0], [30000, 40, 3010], [32000, 40500, 7520], [0, 0, 10520]],
    [[15340, 0, 0], [104300, 0, 3630], [434000, 4434000, 63460]]
]

def calculate_length(x1, y1, x2, y2):
    return ((x1-x2)**2 + (y1 - y2)**2) ** 0.5

def calculate_time (t1,t2):
    return abs(t1-t2)

def lengths(trace):
    previous_x, previous_y = 0, 0
    for index, point in enumerate(trace):
        if point:
            x, y, t = point
            if index > 0:
                yield calculate_length(x, y, previous_x, previous_y)
            previous_x, previous_y = x, y

all_lengths_list = [list(lengths(trace)) for trace in nList]

pprint(all_lengths_list, indent=4)

output

[   [3.6055512754639891],
    [],
    [],
    [30000.026666654816, 40509.401377951763, 51616.373371247231],
    [88960.0, 4446240.8942836197]]

you can get yield by

l = lengths(nList)
next(l) # gives 1st yield
next(l) # gives 2nd

and so on

To get all in a list

>>>list(lengths(nList))

The definition of nList in your code isn't complete and needs a couple of closing ] brackets to be syntactically correct. Also, once a definition of something has been started with an opening ( or [ it's not necessary to explicitly add line-continuation \\ backslash characters if it is then spread across several subsequent lines. This makes them easier to write and a lot cleaner and more natural looking.

With that correction, you could store the values yield ed from the lengths() function in a list like something like this:

all_lengths_list = [[length for length in lengths(trace)] for trace in nList]

or more even more concisely, like so:

all_lengths_list = list((list(lengths(trace)) for trace in nList))

I would also like to mention a few things that you could do simplify and optimize your code. Besides sqrt() , the built-in math module also has a hypot() function which make it easy to calculate distance as your calculate_length() function is doing and will speed it up since more of the mathematical operations will be done in the module's C code instead of Python.

Another thing I noticed was that your lengths() function seems overly complicated and could be greatly streamlined by using some of Python's more advanced features. For starters, why not just have it return the list of points itself, rather than yielding the pieces of one, one-at-a-time.

Beyond that, Python's iterools module contains a number of functions and recipes based on them that make it easy to do iterative things, like calculations. In particular there's one recipe for a generator function called pairwise() which yields the elements of a sequence in tuples, or pairs, of two — which makes it extremely useful for calculating distances as is being done in lengths() .

Below is a modified version of your code incorporating all of the above corrections and suggestions. I also added some stuff at the end to display the results in a fairly readable format.

import itertools
import math

nList = [[[0, 0, 0], [3, 2, 1]],
         [[]],
         [[1, 1, 12]],
         [[0, 0, 0], [30000, 40, 3010], [32000, 40500, 7520], [0, 0, 10520]],
         [[15340, 0, 0], [104300, 0, 3630], [434000, 4434000, 63460]]]

def calculate_length(x1, y1, x2, y2):
    return math.hypot(x1-x2, y1-y2)

def calculate_time (t1,t2):
    return abs(t1-t2)

def pairwise(iterable):  # see http://preview.tinyurl.com/mzbfqlt
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return itertools.izip(a, b)

def lengths(trace):
    return [calculate_length(x1, y1, x2, y2)
                for (x1, y1, t1), (x2, y2, t2) in pairwise(trace)]

all_lengths_list = list(lengths(trace) for trace in nList)

for pts_list, length_list in zip(nList, all_lengths_list):
    print('   points: {}\n'
          'distances: [{}]'.format(
              pts_list,
              ', '.join((format(length, '.2f') for length in length_list))))

Output:

   points: [[0, 0, 0], [3, 2, 1]]
distances: [3.61]
   points: [[]]
distances: []
   points: [[1, 1, 12]]
distances: []
   points: [[0, 0, 0], [30000, 40, 3010], [32000, 40500, 7520], [0, 0, 10520]]
distances: [30000.03, 40509.40, 51616.37]
   points: [[15340, 0, 0], [104300, 0, 3630], [434000, 4434000, 63460]]
distances: [88960.00, 4446240.89]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM