复数字符串格式 [英] Plural String Formatting
问题描述
给出一个 int
s的字典,我正在尝试使用每个数字和一个复数形式格式化字符串.
Given a dictionary of int
s, I'm trying to format a string with each number, and a pluralization of the item.
样本输入 dict
:
data = {'tree': 1, 'bush': 2, 'flower': 3, 'cactus': 0}
示例输出 str
:
'My garden has 1 tree, 2 bushes, 3 flowers, and 0 cacti'
它需要使用任意格式的字符串.
It needs to work with an arbitrary format string.
我想出的最好的解决方案是一个 PluralItem
类,用于存储两个属性 n
(原始值)和 s
(如果为复数,则为字符串's
,否则为空字符串''
).为不同的多元化方法分类
The best solution I've come up with is a PluralItem
class to store two attributes, n
(the original value), and s
(the string 's'
if plural, empty string ''
if not). Subclassed for different pluralization methods
class PluralItem(object):
def __init__(self, num):
self.n = num
self._get_s()
def _get_s(self):
self.s = '' if self.n == 1 else 's'
class PluralES(PluralItem):
def _get_s(self):
self.s = 's' if self.n == 1 else 'es'
class PluralI(PluralItem):
def _get_s(self):
self.s = 'us' if self.n == 1 else 'i'
然后通过理解和 classes
映射来创建新的 dict
:
Then make a new dict
through comprehension and a classes
mapping:
classes = {'bush': PluralES, 'cactus': PluralI, None: PluralItem}
plural_data = {key: classes.get(key, classes[None])(value) for key, value in data.items()}
最后,格式字符串和实现:
Lastly, the format string, and implementation:
formatter = 'My garden has {tree.n} tree{tree.s}, {bush.n} bush{bush.s}, {flower.n} flower{flower.s}, and {cactus.n} cact{cactus.s}'
print(formatter.format(**plural_data))
输出以下内容:
My garden has 1 tree, 2 bushes, 3 flowers, and 0 cacti
对于这种毫无疑问的普遍需求,我很犹豫地将这种复杂的解决方案扔进毛巾里.
For such an undoubtedly common need, I'm hesitant to throw in the towel with such a convoluted solution.
是否有一种使用内置的 format
方法格式化字符串的方法,并且只需最少的附加代码?伪代码可能类似于:
Is there a way to format a string like this using the built-in format
method, and minimal additional code? Pseudocode might be something like:
"{tree} tree{tree(s)}, {bush} bush{bush(es)}, {flower} flower{flower(s)}, {cactus} cact{cactus(i,us)}".format(data)
如果值是复数,或者如果内容具有逗号,则括号返回内容,表示复数/单数
where parentheses return the contents if value is plural, or if contents has comma, means plural/singular
推荐答案
使用自定义格式程序:
import string
class PluralFormatter(string.Formatter):
def get_value(self, key, args, kwargs):
if isinstance(key, int):
return args[key]
if key in kwargs:
return kwargs[key]
if '(' in key and key.endswith(')'):
key, rest = key.split('(', 1)
value = kwargs[key]
suffix = rest.rstrip(')').split(',')
if len(suffix) == 1:
suffix.insert(0, '')
return suffix[0] if value <= 1 else suffix[1]
else:
raise KeyError(key)
data = {'tree': 1, 'bush': 2, 'flower': 3, 'cactus': 0}
formatter = PluralFormatter()
fmt = "{tree} tree{tree(s)}, {bush} bush{bush(es)}, {flower} flower{flower(s)}, {cactus} cact{cactus(i,us)}"
print(formatter.format(fmt, **data))
输出:
1 tree, 2 bushes, 3 flowers, 0 cacti
更新
如果您使用的是Python 3.2+( str.添加了format_map
),您可以使用使用自定义字典的OP的想法(请参见评论).
If you're using Python 3.2+ (str.format_map
was added), you can use the idea of OP (see comment) that use customized dict.
class PluralDict(dict):
def __missing__(self, key):
if '(' in key and key.endswith(')'):
key, rest = key.split('(', 1)
value = super().__getitem__(key)
suffix = rest.rstrip(')').split(',')
if len(suffix) == 1:
suffix.insert(0, '')
return suffix[0] if value <= 1 else suffix[1]
raise KeyError(key)
data = PluralDict({'tree': 1, 'bush': 2, 'flower': 3, 'cactus': 0})
fmt = "{tree} tree{tree(s)}, {bush} bush{bush(es)}, {flower} flower{flower(s)}, {cactus} cact{cactus(i,us)}"
print(fmt.format_map(data))
输出:与上面相同.
这篇关于复数字符串格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!