Python Itertools 仅排列字母和数字

Posted

技术标签:

【中文标题】Python Itertools 仅排列字母和数字【英文标题】:Python Itertools permutations only letters and numbers 【发布时间】:2015-01-01 22:48:31 【问题描述】:

我只需要得到有字母和数字的排列(排列不能是。“A,B,C,D”我需要这样:“A,B,C,1”)

简而言之,排列不能只包含字母,而不仅仅是数字。必须是两者的组合。

我的代码:

import itertools
print list(itertools.combinations([0,1,2,3,4,'a','b','c','d'], 4))

然后我得到:

[(0, 1, 2, 3), (0, 1, 2, 4), (0, 1, 2, 'a'), (0, 1, 2, 'b'), (0, 1, 2, 'c'), (0, 1, 2, 'd'), (0, 1, 3, 4), (0, 1, 3, 'a'), (0, 1, 3, 'b'), (0, 1, 3, 'c'), (0, 1, 3, 'd'), (0, 1, 4, 'a'), (0, 1, 4, 'b'), (0, 1, 4, 'c'), (0, 1, 4, 'd'), (0, 1, 'a', 'b'), (0, 1, 'a', 'c'), (0, 1, 'a', 'd'), (0, 1, 'b', 'c'), (0, 1, 'b', 'd'), (0, 1, 'c', 'd'), (0, 2, 3, 4), (0, 2, 3, 'a'), (0, 2, 3, 'b'), (0, 2, 3, 'c'), (0, 2, 3, 'd'), (0, 2, 4, 'a'), (0, 2, 4, 'b'), (0, 2, 4, 'c'), (0, 2, 4, 'd'), (0, 2, 'a', 'b'), (0, 2, 'a', 'c'), (0, 2, 'a', 'd'), (0, 2, 'b', 'c'), (0, 2, 'b', 'd'), (0, 2, 'c', 'd'), (0, 3, 4, 'a'), (0, 3, 4, 'b'), (0, 3, 4, 'c'), (0, 3, 4, 'd'), (0, 3, 'a', 'b'), (0, 3, 'a', 'c'), (0, 3, 'a', 'd'), (0, 3, 'b', 'c'), (0, 3, 'b', 'd'), (0, 3, 'c', 'd'), (0, 4, 'a', 'b'), (0, 4, 'a', 'c'), (0, 4, 'a', 'd'), (0, 4, 'b', 'c'), (0, 4, 'b', 'd'), (0, 4, 'c', 'd'), (0, 'a', 'b', 'c'), (0, 'a', 'b', 'd'), (0, 'a', 'c', 'd'), (0, 'b', 'c', 'd'), (1, 2, 3, 4), (1, 2, 3, 'a'), (1, 2, 3, 'b'), (1, 2, 3, 'c'), (1, 2, 3, 'd'), (1, 2, 4, 'a'), (1, 2, 4, 'b'), (1, 2, 4, 'c'), (1, 2, 4, 'd'), (1, 2, 'a', 'b'), (1, 2, 'a', 'c'), (1, 2, 'a', 'd'), (1, 2, 'b', 'c'), (1, 2, 'b', 'd'), (1, 2, 'c', 'd'), (1, 3, 4, 'a'), (1, 3, 4, 'b'), (1, 3, 4, 'c'), (1, 3, 4, 'd'), (1, 3, 'a', 'b'), (1, 3, 'a', 'c'), (1, 3, 'a', 'd'), (1, 3, 'b', 'c'), (1, 3, 'b', 'd'), (1, 3, 'c', 'd'), (1, 4, 'a', 'b'), (1, 4, 'a', 'c'), (1, 4, 'a', 'd'), (1, 4, 'b', 'c'), (1, 4, 'b', 'd'), (1, 4, 'c', 'd'), (1, 'a', 'b', 'c'), (1, 'a', 'b', 'd'), (1, 'a', 'c', 'd'), (1, 'b', 'c', 'd'), (2, 3, 4, 'a'), (2, 3, 4, 'b'), (2, 3, 4, 'c'), (2, 3, 4, 'd'), (2, 3, 'a', 'b'), (2, 3, 'a', 'c'), (2, 3, 'a', 'd'), (2, 3, 'b', 'c'), (2, 3, 'b', 'd'), (2, 3, 'c', 'd'), (2, 4, 'a', 'b'), (2, 4, 'a', 'c'), (2, 4, 'a', 'd'), (2, 4, 'b', 'c'), (2, 4, 'b', 'd'), (2, 4, 'c', 'd'), (2, 'a', 'b', 'c'), (2, 'a', 'b', 'd'), (2, 'a', 'c', 'd'), (2, 'b', 'c', 'd'), (3, 4, 'a', 'b'), (3, 4, 'a', 'c'), (3, 4, 'a', 'd'), (3, 4, 'b', 'c'), (3, 4, 'b', 'd'), (3, 4, 'c', 'd'), (3, 'a', 'b', 'c'), (3, 'a', 'b', 'd'), (3, 'a', 'c', 'd'), (3, 'b', 'c', 'd'), (4, 'a', 'b', 'c'), (4, 'a', 'b', 'd'), (4, 'a', 'c', 'd'), (4, 'b', 'c', 'd'), ('a', 'b', 'c', 'd')]

我提出这个问题,如果我想保存到文本文件,请告诉我是否有可能知道所获得文件的大小。我还想知道是否有任何方法可以计算得到所有排列的要求需要多长时间。

非常感谢您。

【问题讨论】:

好问题。我其实在想。 itertools.ifilter?您可以通过分析计算出有多少匹配排列。 @jonrsharpe 我不太明白必须使用过滤器 @jcrashvzla ...什么? 你的问题的标题是关于permutations,而itertools.combinations 给出了子序列。如果你不考虑子序列的顺序,这个函数会产生所有可能的combinations。我猜你可能想要“长度为 4 的所有组合,其中至少有 1 个字母和至少 1 个数字”。你可能会让你的问题更清楚一点。 【参考方案1】:

使用集合交集:

import itertools
import string
numbers = set(range(10))
letters = set(string.ascii_letters)
print([x for x in itertools.combinations([0,1,2,3,4,'a','b','c','d'], 4)
       if set(x) & letters and set(x) & numbers])

【讨论】:

【参考方案2】:

相当幼稚的解决方案..

(x
    for x in itertools.combinations([0,1,2,3,4,'a','b','c','d'], 4)
    if not all(c.isalpha() for c in x) and not all(c.isdigit() for c in x))

【讨论】:

请注意,整数值实际上是整数,而不是数字字符,因此尝试在整数值上评估 isalpha()idigit() 将失败。更改为使用 isinstance 测试将清除此问题。【参考方案3】:

更新 valid_data_types_in_list() 函数以在您的列表中添加额外的约束。

def valid_data_types_in_list(input_list):
    str_type = False
    int_type = False
    for element in input_list:
        if type(element) == str:
            str_type = True
        if type(element) == int:
            int_type = True
    if str_type == int_type == True:
        return True
    return False

import itertools
output = [x for x in list(itertools.combinations([0,1,2,3,4,'a','b','c','d'], 4)) if valid_data_types_in_list(x)]
print output 

【讨论】:

【参考方案4】:
mylist=[]
for x in permutations([0,1,2,"a","b","c"],4):
    print (x)
    mylist.append(x)
for t in permutations([3,4,"c","d"]):
    print (t)
    mylist.append(t)

我将它们分成 3 位 3 位字母、2 位 2 位字母。所以编译 tx 是你的答案。第一个 for 循环不能只包含数字或只包含字母,因为它的排列 4。第二个也不能相同原因。所以将结果编译成一个列表,意味着你的答案。

如何计算时间;

import time
mylist=[]
start=time.time()
for x in permutations([0,1,2,"a","b","c"],4):
    print (x)
    mylist.append(x)
for t in permutations([3,4,"c","d"]):
    print (t)
    mylist.append(t)
end=time.time()
diff=end-start
print ("It took",diff,"seconds")

输出:

...
...
...
('c', 4, 'd', 3)
('c', 'd', 3, 4)
('c', 'd', 4, 3)
('d', 3, 4, 'c')
('d', 3, 'c', 4)
('d', 4, 3, 'c')
('d', 4, 'c', 3)
('d', 'c', 3, 4)
('d', 'c', 4, 3)
It took 0.5800008773803711 seconds
>>> 

编辑有多少排列

from itertools import permutations
import time
mylist=[]
start=time.time()
for x in permutations([0,1,2,"a","b","c"],4):
    print (x)
    mylist.append(x)
for t in permutations([3,4,"c","d"]):
    print (t)
    mylist.append(t)
end=time.time()
diff=end-start
print ("There is  permutations.".format(len(mylist)))
print ("It took",diff,"seconds")

输出:

...
...
...
('d', 3, 4, 'c')
('d', 3, 'c', 4)
('d', 4, 3, 'c')
('d', 4, 'c', 3)
('d', 'c', 3, 4)
('d', 'c', 4, 3)
There is 384 permutations.
It took 0.5120010375976562 seconds
>>> 

【讨论】:

Traceback(最近一次调用最后):文件“fast.py”,第 4 行,在 中为 x 排列([0,1,2,"a","b", "c"],4): NameError: name 'permutations' is not defined ? 你应该导入它,不是吗? 这如何生成像(0, 1, 'c', 'd')(3, 4, 'a', 'b')这样的有效组合? @jcrashvzla 如果这个答案是正确的,你的问题就是错误的,正如 Bas 所指出的那样 这种方法本质上是有缺陷的——即使你让它工作,它也会非常特定于你的输入集和排列中的样本数量。 BlackBear 和 jterrace 提交的答案更好,因为它们不依赖于数据集或排列大小。【参考方案5】:

要使用 filter 或 ifilter,您必须传递一个谓词函数和一个序列。谓词函数对序列中的每个元素进行一次评估,过滤器只会转发那些评估谓词为真的元素。

例如,假设您只需要字符串中的大写字母:

>>> def is_upper(c):
...     return c.upper() == c
...
>>> uppers = filter(is_upper, "lsjdfLSKJDFLljsdlfkjLSFLDJ")
>>> print uppers
LSKJDFLLSFLDJ

或者,如果您只想要某些数字列表中以“6”结尾的数字:

>>> nums_that_end_in_6 = filter(lambda n: n % 10 == 6, range(100))
>>> print nums_that_end_in_6
[6, 16, 26, 36, 46, 56, 66, 76, 86, 96]

(如果你不习惯使用 lambdas,那么当逻辑这么简单时,它们对 filter 很有用。上面的 lambda 与:

def predicate(n):
    return n % 10 == 6

nums_that_end_in_6 = filter(predicate, range(100))

在您的情况下,您将获得一系列字母和 int 值的组合,而您只想要字母和 int 的组合。因此,您需要编写一个谓词函数,当给定您喜欢的序列时返回 True。使用基于集合的解决方案,您的谓词可能如下所示:

ints = set(range(10))
letters = set(string.letters)
def predicate(seq):
    seqset = set(seq)
    return seqset & letters and seqset & ints

使用 any/all 内置函数,您的谓词可能如下所示:

is_int = lambda x : isinstance(x, int)
is_str = lambda x : isinstance(x, str)
def predicate(seq):
    return not(all(is_int(item) for item in seq) or all(is_str(item) for item in seq))

或者,如果您只是想查看您的序列是否包含超过 1 种类型的项目,您可以这样写:

def predicate(seq):
    return len(set(type(item) for item in seq))) > 1

要使用这些谓词中的任何一个,形式都是相同的:

values = list(string.letters) + range(10)
mixed_letter_int_combinations = filter(predicate, combinations(values, 4))

然后您可以根据性能、可读性或您喜欢的任何其他标准选择您喜欢的谓词。

【讨论】:

【参考方案6】:

您可以通过组合两个序列中的非空组合来生成正确的组合。

import itertools

def combinations(a, b, n):
    for i in xrange(1, n):
        for ca in itertools.combinations(a, i):
            for cb in itertools.combinations(b, n-i):
                yield ca + cb

for r in combinations(list('abcd'), [1, 2, 3, 4], 4):
    print r

得到的组合数是choose(A+B, n) - choose(A, n) - choose(B, n),其中A是a中的元素个数,B是b中的元素个数,而“选择”是二项式系数。

【讨论】:

以上是关于Python Itertools 仅排列字母和数字的主要内容,如果未能解决你的问题,请参考以下文章

如何指定仅允许某些第一个组合的 itertools 排列?

Python Itertools 字符串排列

如何生成包含连续数字和字母的混合列表?

【基础】Python3小程序_之排列组合

按数字顺序排列 itertools 产品

python itertools模块实现排列组合