Удалить пустые вложенные списки — Python

Я читаю файл .csv в список, и он добавляет пустые списки, для этого я использую приведенный ниже код.

with open('Scores.csv', 'r') as scores:
    reader = csv.reader(scores)
    tscores = [[str(e) for e in r] for r in reader]

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

[[score1, name1], [], [score2, name2], []]

Я считаю, что он читает \n как пустую строку, поэтому я это получаю, поэтому я попытался удалить пустые списки, используя:

tscores = [tscores.remove(x) for x in tscores if x]

который удаляет пустые вложенные списки, но устанавливает для всех других вложенных списков, содержащих данные, значение None, т. е. [None, None]. Я изменил на:

tscores = [tscores.remove(x) for x in tscores if []]

который полностью стирает все вложенные списки.

Как я могу прочитать файл с тем же выводом (список вложенных списков) без добавления пустых списков или как я могу удалить все пустые списки после чтения?


person PairedPrototype    schedule 01.11.2015    source источник


Ответы (5)


Я думаю, что вы хотите сделать это

tscores = [x for x in tscores if x != []]

которые составляют список только не пустых списков в tscores

person m7mdbadawy    schedule 01.11.2015

В качестве альтернативы ответу пользователя2990008 вы не можете создавать пустые списки в первую очередь:

tscores = [[str(e) for e in r] for r in reader if len(r) > 0]
person Claudiu    schedule 01.11.2015
comment
Это тоже кажется хорошим ответом и, вероятно, наиболее подходящим. РЕДАКТИРОВАТЬ: Это определенно работает. - person PairedPrototype; 02.11.2015

Просто для полноты: в таких случаях я думаю, что понимание списка - не самое простое решение. Здесь функциональное программирование имело бы смысл, имхо.

Чтобы «автоматически» перебирать список и фильтровать определенные элементы, вы можете использовать встроенную функцию фильтр:

In [89]: a = [ [1, 2], [], [3, 4], [], [5, 6], [], [], [9, 5, 2, 5]]

In [91]: filter(lambda x: len(x) > 0, a)
Out[91]: [[1, 2], [3, 4], [5, 6], [9, 5, 2, 5]]

Каждый элемент x списка a передается функции lambda, а возвращаемый список содержит элемент a только тогда и только тогда, когда выполняется условие len(x) > 0. Поэтому возвращается список без вложенных пустых списков.

person daniel451    schedule 02.11.2015
comment
Хм... filter(lambda x: len(x) > 0, a) хуже во всех отношениях, чем [x for x in a if len(x) > 0] - медленнее и менее идиоматично для того же эффекта. - person Claudiu; 02.11.2015
comment
В Python это должно быть медленнее, потому что вызовы функций неэффективны, да - обычно это зависит от реализации. Тем не менее, для целей фильтрации мне (лично) это нравится, потому что это более интуитивно понятно. Этот сценарий похож на один из самых стандартных случаев для filter(). По общему признанию, это решение, основанное на мнении, и просто мои мысли. - person daniel451; 02.11.2015
comment
Да, я обычно делаю так: если функция уже существует/определена в другом месте, я использую filter/map (например, map(str.strip, strs) вместо [x.strip() for x in strs], filter(is_gormed, maybe_gorms) вместо [x for x in maybe_gorms if is_gormed(x)]), но если мне нужно выражение, я использую понимание списка. Люди могут не согласиться даже с этим использованием карты/фильтра - понимание списка действительно легче для глаз (возможно, субъективно) и используется чаще. - person Claudiu; 02.11.2015

Я не уверен, что правильно понял ваш вопрос, но вы можете удалить пустые записи из списка списков (или списка кортежей или списка других последовательностей), используя что-то вроде этого:

#/bin/python
# ...
with open('Scores.csv', 'r') as scores:
    reader = csv.reader(scores)
    tscores = [[str(e) for e in r] for r in reader if len(r)]

... помните, что ваше понимание списка может обрабатывать необязательные условные предложения для фильтрации. Это будет работать только в том случае, если вы можете гарантировать, что каждый элемент списка, который вы просматриваете, поддерживает функцию len() (конечно, вы можете гарантировать это, используя более сложное условие, такое как: hasattr(r, 'len') и len(r)

Примечание: это проверяет только один уровень глубины... он не рекурсивен.

person Jim Dennis    schedule 01.11.2015

tscores = [x for x in tscores if x]

Если список пуст, условное выражение вернет false и, следовательно, не будет включено в tscores.

person PyRsquared    schedule 31.05.2018