简体   繁体   English

如何在Python 2.7中将“ yield”生成器结果存储在列表中?

[英]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? 我将如何在列表中存储calculate_length(x, y, previous_x, previous_y)yield结果?

nList has traces in them with each trace having points with 3 elements, [x,y,t] . nList具有traces在它们与每个trace具有points与3个元素, [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. 您不需要这些行继续反斜杠-现代Python足够聪明,可以知道列表定义不完整,因此它会自动为您执行行继续。

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 . 另外,无需导入数学模块即可计算平方根,您可以使用内置的幂运算符: ** 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 . 为了获得所需的输出,您需要一次将nList的跟踪列表nList给生成器,将捕获的数据捕获到列表中,然后保存在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. 可以在普通的for循环中完成此操作,但是使用列表理解更紧凑,如下面的代码所示。 To display the contents of all_lengths_list I use pprint() from the pprint module. 要显示all_lengths_list的内容,我使用pprint模块中的pprint() 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 你可以通过获得yield

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. 该定义nList在你的代码是不完整的,需要一对夫妇关闭]括号是语法正确。 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: 通过该更正,您可以将lengths()函数yield值存储在类似以下的list

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. 除了sqrt() ,内置的math模块还具有hypot()函数,该函数使您可以轻松地计算calculate_length()函数中的距离,并将加快速度,因为更多的数学运算将在模块的中完成用C代码代替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. 我注意到的另一件事是,您的lengths()函数似乎过于复杂,可以通过使用Python的一些更高级的功能来大大简化。 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. 除此之外,Python的iterools模块还包含许多基于它们的函数和配方,这些函数和配方使执行迭代操作(如计算)变得容易。 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() . 特别是,有一个生成器函数pairwise()配方,该函数可生成一个以两个或两个为一组的元组或成对的序列的元素—这使得它对计算距离非常有用,就像在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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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