Как разделить содержимое файла на пробел и символ конца строки? - PullRequest
1 голос
/ 12 ноября 2009

Когда я делаю следующее понимание списка, я получаю вложенные списки:

channel_values = [x for x in [ y.split(' ') for y in
    open(channel_output_file).readlines() ] if x and not x == '\n']

В основном у меня есть файл, составленный из этого:

7656 7653 7649 7646 7643 7640 7637 7634 7631 7627 7624 7621 7618 7615
8626 8623 8620 8617 8614 8610 8607 8604 8600 8597 8594 8597 8594 4444
<snip several thousand lines>

Где каждая строка этого файла заканчивается новой строкой.

В основном мне нужно добавить каждое число (все они разделены одним пробелом) в список.

Есть ли лучший способ сделать это через понимание списка?

Ответы [ 6 ]

16 голосов
/ 12 ноября 2009

Для этого вам не нужны списочные выражения:

channel_values = open(channel_output_file).read().split()
6 голосов
/ 12 ноября 2009

Просто сделайте это:

channel_values = open(channel_output_file).read().split()

split () будет разделяться в соответствии с пробелами, которые включают ' ' '\t' and '\n'. Он разделит все значения в один список.

Если вы хотите целочисленные значения, вы можете сделать:

channel_values = map(int, open(channel_output_file).read().split())

или со списком:

channel_values = [int(x) for x in open(channel_output_file).read().split()]
2 голосов
/ 12 ноября 2009

Кроме того, причина, по которой исходное понимание списка имело вложенные списки, заключается в том, что вы добавили дополнительный уровень понимания списка с внутренним набором квадратных скобок. Вы имели в виду это:

channel_values = [x for x in y.split(' ') for y in
    open(channel_output_file) if x and not x == '\n']

Другие ответы - все еще лучшие способы написания кода, но это было причиной проблемы.

0 голосов
/ 13 ноября 2009

Если вас не волнует свисающие ссылки на файлы, и вам действительно нужно, чтобы список считывался в память сразу, указатель в одной строке, упомянутый в других ответах, работает:

channel_values = open(channel_output_path).read().split()

В рабочем коде я бы, вероятно, использовал генератор, зачем читать все эти строки, если они вам не нужны?

def generate_values_for_filename(filename):
    with open(filename) as f:
        for line in f:
            for value in line.split():
                yield value

Вы всегда можете составить список позже, если вам действительно нужно сделать что-то другое, кроме перебора значений:

channel_values = list(generate_values_for_filename(channel_output_path))
0 голосов
/ 12 ноября 2009

Есть ли лучший способ сделать это через понимание списка?

Вроде ..

Вместо чтения каждой строки в виде массива с помощью методов .readlines() вы можете просто использовать .read():

channel_values = [x for x in open(channel_output_file).readlines().split(' ')
if x not in [' ', '\n']]

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

out = []
for y in open(channel_output_file).readlines():
    for x in y.split(' '):
        if x not in [' ', '\n']:
            out.append(x)

Или используя цикл for и понимание списка:

out = []
for y in open(channel_output_file).readlines():
    out.extend(
        [x for x in y.split(' ')
        if x != ' ' and x != '\n'])

По сути, если вы не можете сделать что-то просто с помощью понимания списка (или вам нужно их вложить), списочное понимание, вероятно, не лучшее решение.

0 голосов
/ 12 ноября 2009

Ну, еще одна проблема - вы оставляете файл открытым. Обратите внимание, что open является псевдонимом для file.

попробуйте это:

f = file(channel_output_file)
channel_values = f.read().split()
f.close()

Обратите внимание, что они будут строковыми значениями, поэтому, если вы хотите целочисленные, измените вторую строку на

channel_values = [int(x) for x in f.read().split()]

int (x) выдаст ValueError, если в файле есть нецелое значение.

...