Удаление цитат из списка списков

Я написал короткую функцию как часть моей программы, которая удаляет кавычки («) из списка списков. Пример входных данных:

[['"foo"', '"Spam"', '123', '"Angry Badger"'],
 ['"dead"', '"Parrot"', '321', '987']]

Целевой результат будет:

[['foo', 'Spam', '123', 'Angry Badger'],
 ['dead', 'Parrot', '321', '987']]

Этот код, который я использую для анализа:

def quote_strip(input_file):

    for k1, v1 in enumerate(input_file):
        for k2, v2 in enumerate(v1):
            input_file[k1][k2] = v2.lstrip('"').rstrip('"')

    return input_file

Это нормально работает, но я почти уверен, что есть способ сделать это одной строкой. Я просто всегда, кажется, портю понимание, когда у них = войдите в них вот так.

Любая обратная связь будет принята с благодарностью.

2 ответа
2

Я просто всегда, кажется, портю понимание, когда у них = войдите в них вот так.

Я обнаружил, что лучший способ думать о понимании — это думать о понимании как о .appendс.

Давайте изменим ваш внутренний цикл, чтобы использовать .append вместо. Нам не нужно использовать enumerate поскольку мы будем составлять новый список.

def quote_strip(input_file):
    for k1, v1 in enumerate(input_file):
        inner_list = []
        for v2 in v1:
            inner_list.append(v2.lstrip('"').rstrip('"'))
        input_file[k1] = inner_list
    return input_file

Теперь мы можем изменить код на понимание. Я покажу вам шаблон, который мы можем просто скопировать:

my_list = []
for item in other_list:
    my_list.append(item + 1)

становится:

my_list = [
    item + 1
    for item in other_list
]

Мы просто перемещаем все, что находится в append(...) на вершину понимания. И переместите цикл for в конец списка.

def quote_strip(input_file):
    for k1, v1 in enumerate(input_file):
        inner_list = [
            v2.lstrip('"').rstrip('"')
            for v2 in v1
        ]
        input_file[k1] = inner_list
    return input_file

Вы должны заметить, что мы можем убрать необходимость присвоения имени inner_list.

def quote_strip(input_file):
    for k1, v1 in enumerate(input_file):
        input_file[k1] = [
            v2.lstrip('"').rstrip('"')
            for v2 in v1
        ]
    return input_file

Теперь мы можем изменить цикл, чтобы использовать .append опять таки.

def quote_strip(input_file):
    output_list = []
    for v1 in input_file:
        output_list.append([
            v2.lstrip('"').rstrip('"')
            for v2 in v1
        ])
    return output_list

И снова мы можем изменить код на понимание списка.

def quote_strip(input_file):
    return [
        [
            v2.lstrip('"').rstrip('"')
            for v2 in v1
        ]
        for v1 in input_file
    ]

Дополнительный

Я почти уверен, что есть способ сделать это одной строкой

Мы можем выразить понимание в одну строчку, но, пожалуйста, не делай этого. Неважно, сколько строк кода вы напишете, насколько легко ваш код читать. Помещение понимания в одну строку затруднит чтение вашего кода.

  • 1

    также посмотрите этот SO-пример понимания вложенных списков, который может быть удобен: stackoverflow.com/a/8050243/1075247

    — Pureferret

  • 1

    Почему что-то подобное трудно читать ?: A = [[el.strip('"') for el in lst] for lst in A]. Просто любопытно

    — joostblack

  • 1

    @joostblack При беглом чтении кода вы можете легко ошибиться с кодом во многих вещах, поэтому вам нужно фактически прочитать код, а не бегло читать. Кроме того, кодирование с акцентом на количество строк увеличивает плотность кода, обратите внимание, что код OP легче читать, чем многие промежуточные шаги в моем ответе. Потому что плотность моего кода больше, чем у OP. Прочитав код сотен людей, я обнаружил, что код, в котором используются многострочные выражения, легче читать. Трудночитаемый код — это скопление всех мелких частей кода, которые мешают вам бегло читать.

    — Пейлонрайз


Я ни в коем случае не эксперт, и это мой первый ответ здесь. Извините, если это не на должном уровне.

Из вашего вопроса я понял, что ваша цель — сделать так, чтобы ваша функция короче. Мы начнем с перебора родительского списка и сопоставления лямбда-выражения каждому дочернему элементу. Лямбда использует «str.strip ()», который удаляет обе стороны строки.

def v1(in_l):
    for i, l in enumerate(in_l):
        in_l[i] = list(map(lambda x: x.strip('"'), l))
    return in_l

(Приносим извинения, если имена переменных кажутся загадочными. Я хотел сделать их как можно короче.)

Эта функция может быть сокращена до понимания списка:

def v2(in_l):
    return [list(map(lambda x: x.strip('"'), l)) for l in in_l]

И вы можете сократить его с помощью лямбды:

v3 = lambda in_l: [list(map(lambda x: x.strip('"'), l)) for l in in_l]

Для удобства чтения я предлагаю использовать первый. Я побежал timeit.timeit на каждом (включая вашу собственную реализацию), со списком примеров, который вы предоставили в качестве тестового примера, и number = 10000.

Все они собрались примерно 0.015. V1 и V2, казалось, колебались между 0.015 и 0.040. V3 и ваша функция остались 0.015 последовательно.

  • 3

    TL; DR: ваша функция в порядке. Укорочение вообще не дает прироста производительности и приносит в жертву удобочитаемость.

    — картофогэндальф

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *