Уменьшить количество операторов if на python - PullRequest
0 голосов
/ 12 мая 2019

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

--- What kind of submission is this? ---
Sold Property
--- State? ---
Los Angeles
...

и нужно хранить значения после --- --- тегов в переменных. Он работает со всеми этими операторами if, но мне было интересно, возможно ли рефакторинг огромного числа ifs в какую-то структуру (например, словарь), а затем легко записать это в выходной файл.

Вот что я сделал:

"""Open a file to read"""
        for line in res:
            if "Instagram Usernames" in line:
                usernames = next(res)
            if "Date" in line:
                date = next(res)
            if "Address" in line:
                address = next(res)
            if "Neighborhood" in line:
                market = next(res)
            if "State" in line:
                city = next(res)
            if "Asset" in line:
                as_type = next(res)
            if "Sale Price" in line:
                price = next(res)
                if "," in price:
                    price = price.replace(',', '')
                if "$" in price:
                    price = price.replace('$', '')
            if "Square" in line:
                sf = next(res)
                if "," in sf:
                    sf = sf.replace(',', '')
                if "$" in sf:
                    sf = sf.replace('$', '')
            if "Buyer" in line:
                buyer = next(res)
            if "Seller" in line:
                seller = next(res)
            if "Broker" in line:
                brokers = next(res)
            if "Notes" in line:
                notes = next(res)

        """Write to output file"""
        fin.write("IMAGE:  @" + usernames)
        fin.write("DATE: " + date)
        fin.write("ADDRESS: " + address)
        fin.write("MARKET: " + market)
        fin.write("CITY: " + city)
        if as_type == "Multi Family" or "Multi Family\n":
            fin.write("ASSET TYPE: Multifamily\n")
        else:
            fin.write("ASSET TYPE: " + as_type)
        fin.write("PRICE: $" + price)
        if sf in bad_symb:
            fin.write("SF: N/A\n")
            fin.write("PPSF: N/A\n")
        else:
            fin.write("SF: " + sf)
            fin.write("PPSF: $" + "{0:.2f}\n".format(float(price) / float(sf)))
        fin.write("BUYER: " + buyer)
        fin.write("SELLER: " + seller)
        fin.write("BROKERS: " + brokers + "\n")
        if notes != "\n":
            fin.write("NOTES: " + notes + "\n")
        fin.write(footer_sale(market, buyer, seller))

Буду признателен за любую помощь, заранее спасибо!

Ответы [ 3 ]

1 голос
/ 13 мая 2019

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

def strip_currency(s):
    """Function to strip currency and commas from a real number string"""
    return s.replace('$', '').replace(',', '')

# mapping of data labels to attribute/key names
label_attr_map = (
    ('Instagram Usernames', 'usernames'),
    ('Date', 'date'),
    ('Address', 'address'),
    ('Neighborhood', 'market'),
    ('State', 'city'),            # <-- copy-paste bug?
    ('Asset', 'as_type'),
    ('Sale Price', 'price', strip_currency),
    ('Square', 'sf', strip_currency),
    ('Buyer', 'buyer'),
    ('Seller', 'seller'),
    ('Broker', 'broker'),
    ('Notes', 'notes'),
    )

# populate data dict with values from file, as defined in the label_attr_map
data = {}
for line in file:
    # find any matching label, or just go on to the next line
    match_spec = next((spec for spec in label_attr_map if spec[0] in line), None)
    if match_spec is None:
        continue

    # found a label, now extract the next line, and transform it if necessary
    key = match_spec[1]
    data[key] = next(file)
    if len(match_spec) > 2:
        transform_fn = match_spec[2]
        data[key] = transform_fn(data[key])

Теперь сопоставление метки и атрибута легче проверить, а каскад «если» - это всего лишь одно выражение next.

Чтобы записать вывод, просто получите доступ к различным элементам в диктовке data.

0 голосов
/ 12 мая 2019

Используйте лямбда-функцию, определенную для поиска строки следующей строки из списка всех строк строки.

search_func = lambda search_str : [line_list[line_list.index(line)+1] for line in line_list[:-1] if search_str in line]

Получить переменные в качестве ключей и соответствующие конкретные строки поиска в качестве значений в другом словаре:

all_vars_search_dict = {'usernames' : "Instagram Usernames" , 'date' : "Date", 'address' : "Address", 'market' : "Neightbourhood", 'city' : "State",...}

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

all_vals = {k: search_func(all_vars_search_dict[k]) for k in all_vars_search_dict}

При записи в выходной файл вы можете просто перебрать этот словарь.

Примечание. Этот процесс нельзя выполнить для поиска ключевых слов "Square" и "Sale Price" в строках.

0 голосов
/ 12 мая 2019

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

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

res = res.split("\n")

Следующая строка производит словарь;res[::2] выбирает каждый второй элемент в res, начиная с первого элемента (все строки с ---), res[1::2] каждый второй элемент, начиная со второго элемента (все строки с информацией).

Теперь мы выбираем строки с --- в качестве ключа для каждой записи в словаре и информационные строки в качестве значений: key: value;поскольку вы, вероятно, не хотите включать тире, мы удаляем их и пробел в начале и конце с помощью .rstrip("- "):

x = {key.rstrip("- "): value for key in res[::2] for value in res[1::2]}

Теперь вы можете легко индексировать x, чтобы получить желаемыйинформация, которая также упростит запись в ваш выходной файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...