Python понимание двойного списка - PullRequest
0 голосов
/ 30 января 2020

У меня есть список строк, считанных из файла, который мне нужно превратить в 2D-массив:

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

Обратите внимание, что каждая строка заканчивается на ;.

Мне нужно исключить строки со всеми нулями (некоторые строки - все нули в начале и в конце)

I .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]]

Это своего рода возвращение нужного мне двумерного массива, но включая массивы со всеми нулями, поэтому мое условие должно быть не в том месте. За исключением того, что я думал, что условия в конце понимания списка фильтруют элементы, которые go попадают в список.

Тогда я подумал, что мне нужно отфильтровать массив "inside":

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]]

За исключением того, что это удаляет нули, но оставляет маркер (первый элемент каждого массива - маркер)

Я хочу получить только массивы, которые содержат числа, но не нули

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

Ответы [ 2 ]

2 голосов
/ 30 января 2020

Лучше сделать это в несколько строк и не использовать filter(None, ...), так как вы можете просто использовать line[:-1], чтобы испустить последний символ. Во-первых, создание списка в списках может быть сделано: преобразовать все в числа с плавающей запятой:

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

Или, если вы действительно хотите иметь однострочник:

result = [list(map(float, line)) for line in [line[:-1].split(';') for line in lines] if '0' not in line]
1 голос
/ 30 января 2020
[ x
  for x in ([ float(v) for v in line.split(';') if v ]
            for line in lines)
  if any(x[1:]) ]

У нас есть внутренний генератор, который повторяет все строки, разбивает каждую строку, удаляет пустые строки и преобразует все оставшиеся значения в числа с плавающей точкой. Затем у нас есть внешний l oop, который проверяет каждый из этих результатов на наличие только нулей, используя функцию any() на всех элементах, кроме первого.

Это создает все числа с плавающей запятой. Если вам нужно, чтобы первый элемент в каждой строке был плавающим, а остальные должны быть целыми числами, используйте это расширение:

[ 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:]) ]
...