【问题标题】:Strings, ints and leading zeros字符串、整数和前导零
【发布时间】:2014-03-16 21:51:10
【问题描述】:

我需要在一个对象上记录序列号。我们输入许多对象。大多数序列号都是字符串——这些数字不以数字形式使用,只是作为唯一标识符——但它们通常是连续的。此外,由于序列号的唯一 ID 状态,前导零很重要。

在进行数据输入时,最好只输入第一个“连续”序列号(例如 000123),然后输入项目数(例如 5)以获得所需的输出 - 这样我们就可以批量输入数据,见下文:

Obj1.serial = 000123
Obj2.serial = 000124
Obj3.serial = 000125
Obj4.serial = 000126
Obj5.serial = 000127

问题在于,当您将第一个数字作为字符串,转为整数并递增时,您会丢失前导零。

并非所有序列都是连续的 - 并非所有序列都是偶数(例如 FDM-434\RRTASDVI908)

但是那些,我想自动输入。

在 python 中,在迭代之前检查字符串中的前导零(* 以及,我猜,像 0009999 这样的边缘情况),然后在增量后重新应用这些零的最优雅的方法是什么?

我有一个解决这个问题的方法,但它并不优雅。事实上,这是最无聊和最生硬的算法。

这个问题有什么优雅的解决方案吗?

编辑

为了澄清这个问题,我希望序列在增量之后具有相同的位数。

因此,在大多数情况下,这意味着重新应用相同数量的前导零。但是在某些边缘情况下,前导零的数量会减少。例如:009 -> 010; 0099 -> 0100

【问题讨论】:

  • 你先验地知道字段的长度吗?听起来您正试图根据给定的一个序列号来计算它。如果您确实知道要生成的字段的长度,例如 6,那么 '%06d' % n 的优雅就很难被击败。
  • 如果你不这样做,('%0'+str(len(ser))+'d')% (1+int(ser)) 仍然是一个单行...
  • 不,不幸的是,任何特定连续剧或连续剧组的长度都是可变的。
  • 我喜欢@fredtantini 在这里的回答——我得检查一下。是的,我真的很喜欢这个答案。你能把它分解一下吗?

标签: python serialization


【解决方案1】:

试试str.zfill():

>>> s = "000123"
>>> i = int(s)
>>> i
123
>>> n = 6
>>> str(i).zfill(n)
'000123'

【讨论】:

  • 很遗憾,序列号没有固定长度。我们经营着来自世界各地的物品仓库。有些序列号是 2 位,有些是 15。该字段是一个 40 字符的字符串。
  • @datakid: str(i).zfill(len(s)),然后。
【解决方案2】:

我在这里发表我的评论,Obj1.serial 是一个字符串:

Obj1.serial = "000123"

('%0'+str(len(Obj1.serial))+'d') % (1+int(Obj1.serial))

就像@owen-s 回答'%06d' % n:打印数字并用前导0 填充。

关于'%d' % n,只是one way of printing。来自PEP3101

在 Python 3.0 中,% 操作符被一个更强大的 字符串格式化方法,format()。支持 str.format() 方法已向后移植到 Python 2.6。

所以你可能想改用格式...无论如何,% 符号右侧有一个整数,它将替换左侧字符串中的 %d

'%06d' 表示打印至少 6 (6) 位 (d) 长,必要时填写 0 (0)。

由于Obj1.serial 是一个字符串,您必须在增量之前将其转换为整数:1+int(Obj1.serial)。因为右边是一个整数,所以我们可以这样。

现在,对于左边的部分,由于我们不能硬编码 6,我们必须采用 Obj1.serial 的长度。但这是一个整数,所以我们必须将它转换回字符串,并连接到表达式的其余部分 %0 6 d : '%0'+str(len(Obj1.serial))+'d'。因此

('%0'+str(len(Obj1.serial))+'d') % (1+int(Obj1.serial))

现在,格式为 (format-specification):

'{0:06}'.format(n)

以同样的方式替换为

('{0:0'+str(len(Obj1.serial))+'}').format(1+int(Obj1.serial))

【讨论】:

  • 公平地说,我是在安顿下来后自己阅读的——当我阅读单行时,我仍然会看到克林贡语。我真的需要集中精力来分解它。
【解决方案3】:

您可以提前检查字符串的长度,然后使用rjust 填充到相同的长度:

>>> s = "000123"
>>> len_s = len(s)
>>> i = int(s)
>>> i
123
>>> str(i).rjust(len_s, "0")
'000123'

您可以使用以下方法检查所有数字的序列号:

if serial.isdigit():

【讨论】:

  • " 然后在增量后重新应用这些零?"我认为009 + 1 不会是0010,而是010。增量可能会改变前导 0 的长度...
  • 你是对的@fredtantini 这就是我提到边缘情况的原因
  • @fredtantini 这将保持字段相同的长度;如果 OP 想要相同的 number 个前导零,则需要进行修改。
  • @jonrsharpe 你是对的,我的解释很懒惰。就我的问题措辞不佳而言,您的回答是正确的,对此我深表歉意。我的意思是我想要相同数量的数字,并带有适当数量的前导零。
  • @datakid 没问题;为了清楚起见,我建议你用你认为在你的边缘情况下应该发生的事情来更新这个问题。
猜你喜欢
  • 1970-01-01
  • 2018-12-23
  • 1970-01-01
  • 1970-01-01
  • 2014-08-09
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多