Python Itertools permutations仅包含字母和数字

4

我需要获取只包含字母和数字的排列组合(排列不能仅为"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')]

我推动这个问题,请告诉我是否有可能知道获取的文件大小,如果我想保存到文本文件。 我还想知道是否有任何方法可以计算获取所有排列需要多长时间。非常感谢您的帮助。

好问题。我正在思考。 - GLHF
itertools.ifilter?您可以通过分析计算出有多少匹配的排列组合。 - jonrsharpe
@jonrsharpe 我不太明白你要使用哪种过滤器。 - jcrashvzla
@jcrashvzla ...什么? - jonrsharpe
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Bas Swinckels
@BasSwinckels 没错,我向您道歉,我的英语不是很好。 - jcrashvzla
6个回答

7
使用集合交集:
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])

4
相当幼稚的解决方案..
(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))

1
请注意,整数值实际上是整数,而不是数字字符,因此尝试在整数值上评估isalpha()idigit()将失败。更改为使用isinstance测试将解决这个问题。 - PaulMcG

0
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行,在循环语句中使用了permutations([0,1,2,"a","b","c"],4)。 NameError: 未定义名称'permutations'。 - jcrashvzla
你应该导入它了,不是吗? - GLHF
2
这个程序是如何生成有效的组合,比如(0, 1, 'c', 'd')或者(3, 4, 'a', 'b')的呢? - Bas Swinckels
3
如果这个回答是正确的,那么你的问题就是错误的,正如Bas所指出的那样。 - jonrsharpe
3
这种方法本质上存在缺陷 - 即使你让它工作,它也会非常依赖于你的输入集和排列样本数量。BlackBear和jterrace提交的答案更好,因为它们不太依赖于数据集或排列大小。 - PaulMcG

0

更新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 

0
要使用filter或ifilter,您必须传递一个谓词函数和一个序列。谓词函数对序列中的每个元素进行一次评估,而filter仅会将那些谓词评估为True的元素转发。
例如,假设您只想在字符串中获取大写字母:
>>> 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]

(如果您不习惯使用lambda表达式,当逻辑如此简单时,它们与filter一起非常有用。上面的lambda表达式等同于:

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

nums_that_end_in_6 = filter(predicate, range(100))

在您的情况下,您正在获取字母和整数值的组合序列,并且您只想要那些混合了字母和整数的值。因此,您需要编写一个谓词函数,当给定符合您要求的序列时返回True。使用基于集合的解决方案,您的谓词可能如下所示:
ints = set(range(10))
letters = set(string.letters)
def predicate(seq):
    seqset = set(seq)
    return seqset & letters and seqset & ints

使用任意/全部内置函数,您的谓词可能如下所示:

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))

或者,如果您只想查看您的序列是否包含多种类型的项目,您可以编写:

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))

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

0

您可以通过将两个序列的非空组合进行组合来生成适当的组合。

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中元素的数量,“choose”是二项式系数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接