Python实现为1-3个有序不重复元素组合分配唯一整数ID
解决方案
核心问题:你需要的是有序不重复排列而非无序组合,itertools.combinations生成的是无序结果,自然不符合要求,改用itertools.permutations即可解决。
方法1:预生成映射表(推荐,元素数≤100都完全够用)
20个元素的情况下,1~3长度的排列总数只有 20 + 20*19 + 20*19*18 = 7240 条,预生成映射表查询效率为O(1),实现简单不易出错。
代码示例:
import itertools elems = ('banana', 'apple', 'orange', 'melon') # 预生成排列到id的映射 perm_to_id = {} current_id = 1 # 按长度1、2、3的顺序生成 for length in [1, 2, 3]: # 按elems的顺序生成所有长度为length的有序不重复排列 for perm in itertools.permutations(elems, length): perm_to_id[perm] = current_id current_id += 1 # 封装查询函数 def get_unique_id(*args): # 输入合法性检查(可选) if len(args) not in (1,2,3): raise ValueError("只能输入1~3个元素") if len(set(args)) != len(args): raise ValueError("输入元素不能重复") for elem in args: if elem not in elems: raise ValueError(f"元素{elem}不在预设列表中") return perm_to_id[tuple(args)]
测试用例:
print(get_unique_id('banana')) # 输出1 print(get_unique_id('banana', 'apple')) # 输出2 print(get_unique_id('banana', 'melon', 'orange')) # 输出10 print(get_unique_id('apple')) # 输出11
方法2:数学公式直接计算(无需预生成,适合元素量极大的场景)
如果你不想预生成所有排列,可以通过排列数公式直接计算id:
elems = ('banana', 'apple', 'orange', 'melon') elem_to_idx = {e:i for i,e in enumerate(elems)} n = len(elems) def get_unique_id(*args): k = len(args) if k not in (1,2,3): raise ValueError("只能输入1~3个元素") # 先计算所有长度小于k的排列总数 base = 0 if k >=2: base += n if k >=3: base += n * (n-1) # 计算当前长度k下的排列偏移量 used = set() offset = 0 for i in range(k): current_elem = args[i] current_idx = elem_to_idx[current_elem] # 统计当前位置之前有多少个未使用的元素 cnt = 0 for idx in range(current_idx): if idx not in used: cnt +=1 # 计算剩余位置的排列数 remain_pos = k - i -1 perm_count = 1 for j in range(remain_pos): perm_count *= (n - i -1 -j) offset += cnt * perm_count used.add(current_idx) return base + offset + 1
内容的提问来源于stack exchange,提问作者Gabriel
相关产品推荐
相关产品推荐

