【问题标题】:Possible to use string formatting to split a string value?可以使用字符串格式来拆分字符串值吗?
【发布时间】:2017-11-17 19:39:02
【问题描述】:

编辑: 我坚持使用 python 2.7.5 ...

另一个编辑: 明确需要在模板中进行更改,而不是在处理字典的代码中。

我正在使用字符串格式化程序从模板构建路径。

我知道我可以做到:

currentUser = {'first': "Monty", 'last': "Python"}
template = '/usr/{user[last]}/{user[first]}' # will come from a config file
template.format(user=currentUser)
# Result: '/usr/Python/Monty'

但是在

的情况下
currentUser = {'first': "Raymond", 'last': "Luxury-Yacht"}

有没有办法分割,比如说,- 并使用索引?

# something like:
template = '/usr/{user[last].split(-)[0]/{user[first]}' # will come from a config file
template.format(user=currentUser)
# Result: '/usr/Luxury/Raymond'

选择的决定:

  • 拆分哪个键
  • 由什么字符
  • 从拆分中使用哪个索引

必须来自模板字符串;如果当前的迷你语言无法做到这一点,我将不得不编写一个自定义格式化程序。

免责声明:这个例子有点做作,不实用,我知道。我实际上正在处理一个数据库,其中两个关键信息位存储在一个字段中,并由下划线 -_- 连接。我知道我可以在从数据库中提取数据后对数据进行后处理,但是由于每个项目的该字段的约定不同,我什至不能假设拆分操作是有效的(某些项目上的一些值赢了'没有下划线问题)。我希望能够为用户提供模板“语言”,而不是围绕每个约定编写解决方案,以便每个项目自己确定如何提取数据,适应他们选择的任何命名约定,并相应地配置他们的模板.

TL/DR:我不是在寻找修复传入数据的解决方案——我在探索使用 Python 的字符串格式迷你语言拆分字符串的可能性。

【问题讨论】:

  • 我很乐意编写一个自定义 string.Formatter 将这种行为引入规范,但如果该功能已经存在,我不想重新发明轮子。

标签: python string split format


【解决方案1】:

您可以使用字典理解:

currentUser = {'first': "Raymond", 'last': "Luxury-Yacht"}
template = '/usr/{user[last]}/{user[first]}'
template.format(user={a:b.split('-')[0] if '-' in b else b for a, b in currentUser.items()})

输出:

'/usr/Luxury/Raymond'

这也适用于您的第一个示例:

currentUser = {'first': "Monty", 'last': "Python"}
template = '/usr/{user[last]}/{user[first]}'
template.format(user={a:b.split('-')[0] if '-' in b else b for a, b in currentUser.items()})

输出:

'/usr/Python/Monty'

附带说明一下,在格式中使用解包 (**) 来删除字符串本身中的 __getitem__ 调用更符合 Pythonic:

currentUser = {'first': "Raymond", 'last': "Luxury-Yacht"}
template = '/usr/{last}/{first}'.format(**{a:b.split('-')[0] if '-' in b else b for a, b in currentUser.items()})

【讨论】:

  • 我的限制是我不能用代码拆分字符串,我必须依靠模板字符串告诉python如何提取项目。跨度>
  • {key: val.split("-")[0] if key == "last" else val for key, val in currentUser.items()} 只拆分姓氏。
【解决方案2】:

如果您对 Python 3.6 持开放态度,可以使用f-strings

users = [{'first': "Raymond", 'last': "Luxury-Yacht"}, 
         {'first': "Monty", 'last': "Python"}]

sep = '-'
for user in users:
    path = f"/usr/{user['last'].split(sep)[0]}/{user['first'].split(sep)[0]}"
    print(path)

/usr/Luxury/Raymond
/usr/Python/Monty

但是,如果你想在 Python 2 中坚持你的 dict 样式格式,你可以使用当前模板和一个小的包装类来清理字典值:

class Wrapper(object):
    __slots__ = ('sep', 'dct')

    def __init__(self, dct, sep='-'):
        self.sep = sep
        self.dct = dct

    def __getitem__(self, key):
        return self.dct[key].split(self.sep)[0]

template = '/usr/{user[last]}/{user[first]}'
for usr in map(Wrapper, users):
    path = template.format(user=usr)
    print(path) 

/usr/Luxury/Raymond
/usr/Python/Monty

【讨论】:

  • 该死!这看起来正是我想要的,但不幸的是,我被 Python2 困住了
  • @RyandeKleer Python2 很快就会被淘汰,因此无论如何将代码库迁移到 Python3 可能是有意义的。
  • @Ajax1234 绝对是,并且为此做准备,我们正在编写尽可能多的 2/3 合规性,但我们无法触发:直到某些软件应用程序(VFX/电影行业)进行转换,我们被困在 2 :(
  • @RyandeKleer 啊,我明白了。
  • @MosesKoledoye 包装器 假定 分隔符,问题是我不能。这就是为什么我需要选择在那些编写模板(非程序员)而不是在代码中的人手中。也许我应该澄清我的问题......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 2012-02-29
  • 1970-01-01
  • 2011-02-10
  • 2015-12-28
  • 1970-01-01
相关资源
最近更新 更多