Учитывая строку шаблона/форматирования "{foo}_{bar}"
, как я могу программно извлечь необходимые ключи форматирования ["foo", "bar"]
?
У меня есть параметры для различных экспериментов
[
{"parameters": {"foo": 1, "bar": 2}, "format": `"{foo}_{bar}"`},
{"parameters": {"biz": 3}, "format": "{biz}_{baz}"}
]
Как видите, во втором наборе параметров отсутствует ключ baz
. Поэтому, когда я делаю что-то вроде
"{biz}_{baz}".format(**parameters)
, вызывает KeyError, потому что baz
отсутствует.
Я хочу заменить все отсутствующие параметры на NR
и заполнить все доступные параметры их значениями.
Результат тогда:
[
{"parameters": {"foo": 1, "bar": 2}, "format": `"{foo}_{bar}"`, "formatted": "1_2"},
{"parameters": {"biz": 3}, "format": "{biz}_{baz}", "formatted": "3_NR"}
]
Для контекста: у меня есть более 100 строк, и нет согласованности между ожидаемыми параметрами, необходимыми для этой строки.
@BramVanroy дубликат точно отвечает на выделенное жирным шрифтом первое предложение
@jonrsharpe Точно, но если вы прочитаете дальше, у этого пользователя на самом деле есть очень конкретная конечная цель. Я считаю, что это то, вокруг чего вращается этот вопрос, поскольку это та часть, которая на самом деле поможет им намного больше, чем просто этот первый вопрос. Я уверен, что если OP приложит некоторые усилия, чтобы переписать пост, чтобы подчеркнуть конечную цель, его можно будет открыть повторно.
@BramVanroy, может быть, но голосование за открытие до того, как они это сделают, кажется преждевременным, и, возможно, они спросили о том, на чем они на самом деле застряли.
Привет, ребята, выделенное жирным шрифтом предложение - это все, с чем мне действительно нужна помощь. Кажется, что правильный ответ на этот вопрос на самом деле является принятым ответом в связанном посте. stackoverflow.com/questions/22830226/…. Прежде чем задать вопрос, я провел поиск по переполнению стека, но почему-то пропустил этот пост. Спасибо вам обоим за помощь!
@BramVanroy, так что теперь он снова открыт, несмотря на то, что ответ обманщика решает проблему ОП; это неоптимальный результат, потому что следующий человек, который найдет это, увидит хрупкое решение ниже, если он не войдет в комментарии или не прочитает связанные вопросы. Было бы хорошо подождать, пока ОП уточнит через редактирование, нужно ли повторно открывать вопрос.
@jonrsharpe Ты прав. Я должен был подождать с повторным голосованием, пока OP не изменит свой пост, что в конце концов они сочли ненужным. Не уверен, что все еще можно проголосовать за закрытие. Извини, моя ошибка.
Вы можете эффективно собрать необходимые имена параметров из строки, а затем проверить, есть ли какие-либо отсутствующие ключи, проверив сходство наборов между фактическими ключами. Если отсутствуют ключи, добавьте их со значением «NR». Наконец, используйте .format
, чтобы правильно отформатировать строку в «форматированный» ключ.
ds = [
{"parameters": {"foo": 1, "bar": 2}, "format": "{foo}_{bar}"},
{"parameters": {"biz": 3}, "format": "{biz}_{baz}"}
]
for d in ds:
# Copy params so that we do not change params in-place
params = d["parameters"]
req_keys = set(d["format"][1:-1].split("}_{"))
missing_keys = req_keys.difference(params.keys())
if len(missing_keys) > 0:
params = {**params, **{key: "NR" for key in missing_keys}}
d["formatted"] = d["format"].format(**params)
print(ds)
# [{'parameters': {'foo': 1, 'bar': 2}, 'format': '{foo}_{bar}', 'formatted': '1_2'}, {'parameters': {'biz': 3}, 'format': '{biz}_{baz}', 'formatted': '3_NR'}]
Сделал почти так же, только заменил req_keys = set(d["format"][1:-1].split("}_{"))
на req_keys=[var for _, var, _, _ in Formatter().parse(d['format']) if var]
. Это позволяет избежать привязки всего к "}_{" на случай, если в будущем произойдут изменения.
@jonrsharpe Мне кажется, что это не точная копия, поскольку его намерения немного отличаются или сложны. Хотя название немного неудачное.