簡體   English   中英

具有 0-9 和 AZ 的 Python 序列號生成器

[英]Python sequential number generator with 0-9 and A-Z

我正在嘗試完成一個數字生成器,它遞增數字(0-9)和字符(AZ 不區分大小寫),以便在我們的軟件項目中唯一標識某些對象。 輸出字符串的長度應為 14。

生成器應該能夠創建一系列序列號/字符(參見下面的示例),這些序列號/字符將用於運行一些帶有數據庫的 python 應用程序的潛在數百台設備。 我們希望實現以下邏輯並將這些序列號范圍“提供”給設備,因此我們確保我們在所有系統中都有唯一的 ID。 我們更喜歡這種邏輯而不是經典的隨機 id 創建。

增量應該從右到左開始。 數字以 0-9 開頭。 如果達到 9,則索引應從 AZ 開始遞增。 如果達到 Z,則左側索引號應從 0 增加到 1 或 9 => AZ(高一)。 然后,正確的索引應該再次以相同的邏輯遞增,從 0 => 1-9 開始,然后是 AZ。

一些示例輸出:

  • 00000000000009
  • 0000000000000A
  • 0000000000000B

或者:

  • 0000000000000Z
  • 00000000000010
  • 00000000000011

等等。

該函數還應該能夠以給定的數字開始,例如 00000000005X ,然后以 00000000005Y 等繼續。

如何在 Python 中構建它?

您可以使用string模塊中的常量來獲取所有數字/大寫 ASCII 字符,然后使用itertools.product生成 ID:

import string
import itertools

# Create the iterable.
characters = string.digits + string.ascii_uppercase
n = 14
id_iterable = map(''.join, itertools.product(characters, repeat=n))

# Get the first 50 elements in the iterable and print them out (for demo purposes).
head = list(itertools.islice(id_iterable, 50))
print(*head, sep='\n')

這輸出:

00000000000000
00000000000001
00000000000002
00000000000003
00000000000004
00000000000005
00000000000006
00000000000007
00000000000008
00000000000009
0000000000000A
0000000000000B
0000000000000C
0000000000000D
0000000000000E
0000000000000F
0000000000000G
0000000000000H
0000000000000I
0000000000000J
0000000000000K
0000000000000L
0000000000000M
0000000000000N
0000000000000O
0000000000000P
0000000000000Q
0000000000000R
0000000000000S
0000000000000T
0000000000000U
0000000000000V
0000000000000W
0000000000000X
0000000000000Y
0000000000000Z
00000000000010
00000000000011
00000000000012
00000000000013
00000000000014
00000000000015
00000000000016
00000000000017
00000000000018
00000000000019
0000000000001A
0000000000001B
0000000000001C
0000000000001D

你可以試試:

import numpy as np

def f(start):
    n = int(start, base=36)
    while True:
        yield np.base_repr(n, 36).rjust(14,"0")
        n += 1

然后:

g = f('0000000000012S')

for i in range(10):
    print(next(g))

它給:

0000000000012S
0000000000012T
0000000000012U
0000000000012V
0000000000012W
0000000000012X
0000000000012Y
0000000000012Z
00000000000130
00000000000131

該程序僅使用string模塊,而不是itertools我還添加了名為LENGTHSTART的常量,您可以更改它們

代碼:

from string import ascii_uppercase

sequence = [str(i) for i in range(10)] + list(ascii_uppercase)

LENGTH = 14
START = '0' * LENGTH

last = list(START)
while last != list('Z' * LENGTH):
    print(''.join(last))
    i = 1
    while last[-i] == 'Z':
        last[-i] = '0'
        i += 1
    last = last[:-i] + [sequence[sequence.index(last[-i]) + 1]] + last[LENGTH-i+1:]

輸出:

00000000000000 
00000000000001 
00000000000002 
00000000000003 
00000000000004 
00000000000005 
00000000000006 
00000000000007 
00000000000008 
00000000000009 
0000000000000A 
0000000000000B 
0000000000000C 
0000000000000D 
0000000000000E 
0000000000000F 
0000000000000G 
0000000000000H 
0000000000000I 
0000000000000J 
0000000000000K 
0000000000000L 
0000000000000M 
0000000000000N 
0000000000000O 
0000000000000P 
0000000000000Q 
0000000000000R 
0000000000000S 
0000000000000T 
0000000000000U 
0000000000000V 
0000000000000W 
0000000000000X 
0000000000000Y 
0000000000000Z 
00000000000010 
00000000000011 
00000000000012 
00000000000013 
00000000000014 
00000000000015 
00000000000016 
00000000000017 
00000000000018 
00000000000019 
0000000000001A 
0000000000001B 
0000000000001C 
0000000000001D 
0000000000001E 
0000000000001F 
0000000000001G
...

正在使用您的問題作為練習,看看我是否可以在 JS 中快速實現該算法,並不打算提供解決方案,因為我預計這個“家庭作業式”問題會很快得到答案。 @bb1 的 numpy 解決方案似乎相當不錯,itertools 方法也是如此(盡管它實際上並未編寫為生成器函數)。 雖然兩者都有圖書館開銷。

有點驚訝沒有一個好的算法方法,只有圖書館的答案。 所以我想我會分享我的,即使它是用錯誤的語言。 在 Python 中采用這個應該不會太棘手,除了可能將 JS 閉包轉換為 Python 中的生成器函數。 如本文所述,如果我們碰巧點擊“ZZZZZZZZZZZZZZ”,則生成的下一個值是“00000000000000”,然后我們重新啟動。

function GetGenerator(start_val) {
    
    const min_val = "0"
    const id_len = 14;
    
    if (start_val && start_val.length != id_len) 
        throw "Initial value length isn't " + id_len
    
    // A dictionary mapping each character to the next & 'Z' to 'undefined'
    const incrementer = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
        .reduce((acc, cur, idx, arr) => (acc[cur] = arr[idx+1], acc), {})
    
    const counter = start_val ? start_val.split("") : Array(id_len).fill(min_val)
    
    function increment() {
        //  Moving backwards through the array  <--
        // ["0", "0", "0", "0", ... , "0", "5", "X" ]
        for(let i = id_len - 1; i >= 0; i--) {
            const next = incrementer[counter[i]]
            if (next) {
                counter[i] = next
                return
            } else {
                counter[i] = min_val
                // No return, it's a carry. Increment the next index.
            }                
        }
    }
    
    return function gen() {
        increment()
        return counter.join("")
    }
}

像這樣使用:

const generator = GetGenerator("0000000000005X")

generator()
>>> "0000000000005Y"
generator()
>>> "0000000000005Z"
generator()
>>> "00000000000060"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM