简体   繁体   English

Python双列表理解

[英]Python double list comprehension

I have a list of strings read from a file I need to turn into a 2D array:我有一个从文件中读取的字符串列表,我需要将其转换为二维数组:

IN >> lines = ['0.1;0;0;0;', '0.2;0;0;0;', '0.3;1;1;1;', '0.4;2;2;2;', '0.5;0;0;0;']
# Goes on for a few thousand lines

Note each string ends in ;注意每个字符串都以;结尾; . .

I need to exclude lines with all zeroes (some lines are all zeroes at the start and at the end)我需要排除全为零的行(有些行在开头和结尾都是零)

I .split() on ;.split(); but filter None to remove the empty values I will get at the end of each returned array from the .split() .filter None以删除我将从.split()返回的每个数组末尾获得的空值。

data_array = [list(filter(None, line.split(';'))) for line in lines if line.split(';')[1] != '0']

OUT >> data_array = [[0.1, 0, 0, 0], [0.2, 0, 0, 0], [0.3, 1, 1, 1], [0.4, 2, 2, 2], [0.5, 0, 0, 0]]

This is kind of returning the 2D array I need, but including the arrays with all zeroes, so my conditional must be at the wrong place.这有点返回我需要的二维数组,但包括全为零的数组,所以我的条件必须在错误的地方。 Except I thought conditions at the end of a list comprehension filter the elements that go into the list.除了我认为列表理解末尾的条件会过滤进入列表的元素。

Then I thought I needed to filter on the "inside" array:然后我想我需要过滤“内部”数组:

data_array = [[l for l in (filter(None, line.split(';'))) if l != '0'] for line in lines]

OUT >> data_array = [[0.1], [0.2], [0.3, 1, 1, 1], [0.4, 2, 2, 2], [0.5]]

Except this is removing the zeroes but leaving the marker (the first element of each array is a marker)除了这是删除零但留下标记(每个数组的第一个元素是一个标记)

What I'm looking to get is just the arrays that contain numbers but not zeroes我想要得到的只是包含数字但不包含零的数组

DESIRED OUTPUT >> data_array = [[0.3, 1, 1, 1], [0.4, 2, 2, 2]]

It is cleaner to do this over multiple lines and not using the filter(None, ...) as you can just use line[:-1] , to emit the last character.在多行上执行此操作而不使用filter(None, ...)更干净,因为您可以只使用line[:-1]来发出最后一个字符。 First creating the list in lists, can be done by:首先在列表中创建列表,可以通过以下方式完成:

nested_list = [line[:-1].split(';') for line in lines] 

You can then iterate over the inner lists to check if they contain a 0:然后,您可以遍历内部列表以检查它们是否包含 0:

filtered_list = [line for line in nested_list if '0' not in line]

Then we need to convert everything to floats:然后我们需要将所有内容转换为浮点数:

result = [list(map(float, line)) for line in filtered_list]

Or if you really want to have a one-liner:或者,如果你真的想要一个单线:

result = [list(map(float, line)) for line in [line[:-1].split(';') for line in lines] if '0' not in line]
[ x
  for x in ([ float(v) for v in line.split(';') if v ]
            for line in lines)
  if any(x[1:]) ]

We have an inner generator which iterates all lines, splits each line, removes the empty strings and converts all remaining values to floats.我们有一个内部生成器,它迭代所有行,拆分每一行,删除空字符串并将所有剩余值转换为浮点数。 Then we have an outer loop which checks each of these results for containing only zeros by using the any() function on all but the first element.然后我们有一个外循环,它通过对除第一个元素之外的所有元素使用any()函数来检查这些结果中的每一个是否只包含零。

This produces all floats.这将产生所有浮点数。 If you need only the first element in each line to be a float and the rest shall be integers, then use this extension:如果您只需要每行中的第一个元素是一个浮点数,其余的应该是整数,那么使用这个扩展:

[ x
  for x in ([ (int if i else float)(v)
              for i, v in enumerate(line.split(';'))
              if v ]
            for line in lines)
  if any(x[1:]) ]

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

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