Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 这一组所有的一行函数在做什么?_Python_Lambda_Set_List Comprehension - Fatal编程技术网

Python 这一组所有的一行函数在做什么?

Python 这一组所有的一行函数在做什么?,python,lambda,set,list-comprehension,Python,Lambda,Set,List Comprehension,我在上找到了这个单行函数,它创建了一组可以从作为参数传递的列表中创建的所有集合 f = lambda x: [[y for j, y in enumerate(set(x)) if (i >> j) & 1] for i in range(2**len(set(x)))] 有人能解释一下这个函数是如何工作的吗?要构造powerset,迭代2**len(set(x))会给出集合的所有二进制组合 range(2**len(set(x))) == [00000, 00001, 0

我在上找到了这个单行函数,它创建了一组可以从作为参数传递的列表中创建的所有集合

f = lambda x: [[y for j, y in enumerate(set(x)) if (i >> j) & 1] for i in range(2**len(set(x)))]

有人能解释一下这个函数是如何工作的吗?

要构造powerset,迭代
2**len(set(x))
会给出集合的所有二进制组合

range(2**len(set(x))) == [00000, 00001, 00010, ..., 11110, 11111]
现在,您只需测试该位是否在
i
中设置,以查看是否需要将其包括在该集中,例如:

>>> i = 0b10010
>>> [y for j, y in enumerate(range(5)) if (i >> j) & 1]
[1, 4]
虽然我不确定每次迭代调用
set(x)
的效率有多高。有一个小技巧可以避免:

f = lambda x: [[y for j, y in enumerate(s) if (i >> j) & 1] for s in [set(x)] for i in range(2**len(s))]
使用
itertools
的两个其他表单:

import itertools as it
f1 = lambda x: [list(it.compress(s, i)) for s in [set(x)] for i in it.product((0,1), repeat=len(s))]
f2 = lambda x: list(it.chain.from_iterable(it.combinations(set(x), r) for r in range(len(set(x))+1)))
注意:如果您删除
list()
,最后一个选项可能会返回一个iterable vs list,这取决于使用情况,这可能会节省一些内存

查看25个0-50随机数列表的一些计时:

%%timeit binary: 1 loop, best of 3: 20.1 s per loop
%%timeit binary+hack: 1 loop, best of 3: 17.9 s per loop
%%timeit compress/product: 1 loop, best of 3: 5.27 s per loop
%%timeit chain/combinations: 1 loop, best of 3: 659 ms per loop

要构造powerset,在
2**len(set(x))
上迭代可以得到集合的所有二进制组合

range(2**len(set(x))) == [00000, 00001, 00010, ..., 11110, 11111]
现在,您只需测试该位是否在
i
中设置,以查看是否需要将其包括在该集中,例如:

>>> i = 0b10010
>>> [y for j, y in enumerate(range(5)) if (i >> j) & 1]
[1, 4]
虽然我不确定每次迭代调用
set(x)
的效率有多高。有一个小技巧可以避免:

f = lambda x: [[y for j, y in enumerate(s) if (i >> j) & 1] for s in [set(x)] for i in range(2**len(s))]
使用
itertools
的两个其他表单:

import itertools as it
f1 = lambda x: [list(it.compress(s, i)) for s in [set(x)] for i in it.product((0,1), repeat=len(s))]
f2 = lambda x: list(it.chain.from_iterable(it.combinations(set(x), r) for r in range(len(set(x))+1)))
注意:如果您删除
list()
,最后一个选项可能会返回一个iterable vs list,这取决于使用情况,这可能会节省一些内存

查看25个0-50随机数列表的一些计时:

%%timeit binary: 1 loop, best of 3: 20.1 s per loop
%%timeit binary+hack: 1 loop, best of 3: 17.9 s per loop
%%timeit compress/product: 1 loop, best of 3: 5.27 s per loop
%%timeit chain/combinations: 1 loop, best of 3: 659 ms per loop

让我们重写一下,然后一步一步地分解:

f = lambda x: [[y for j, y in enumerate(set(x)) if (i >> j) & 1] for i in range(2**len(set(x)))]
相当于:

def f(x):
    n = len(set(x))
    sets = []
    for i in range(n): # all combinations of members of the set in binary
        set_i = []
        for j, y in enumerate(set(x)):
            if (i>>j) & 1: #check if bit nr j is set
                set_x.append(y)
        sets.append(set_i)
    return sets
对于像
[1,2,3,4]
这样的输入列表,会发生以下情况:

n=4
range(2**n)=[0,1,2,3...15]
以二进制形式表示:

0,1,10,11,100...1110,1111
Enumerate使用其索引生成y的元组,因此在本例中:

[(0,1),(1,2),(2,3),(3,4)]
(i>>j)&1
部分可能需要一些解释。
(i>>j)
将数字
i
j
向右移位,例如十进制:
4>>2=1
,或二进制:
100>>2=001
&
是按位
运算符。这将检查两个操作数的每一位是否为1,并以数字形式返回结果,就像过滤器一样:
10111&11001=10101


在本例中,它检查位置
j
处的位是否为1。如果是,则将相应的值添加到结果列表中。通过这种方式,组合的二进制映射将转换为列表列表,并返回该列表。

让我们稍微重写它,然后一步一步地将其分解:

f = lambda x: [[y for j, y in enumerate(set(x)) if (i >> j) & 1] for i in range(2**len(set(x)))]
相当于:

def f(x):
    n = len(set(x))
    sets = []
    for i in range(n): # all combinations of members of the set in binary
        set_i = []
        for j, y in enumerate(set(x)):
            if (i>>j) & 1: #check if bit nr j is set
                set_x.append(y)
        sets.append(set_i)
    return sets
对于像
[1,2,3,4]
这样的输入列表,会发生以下情况:

n=4
range(2**n)=[0,1,2,3...15]
以二进制形式表示:

0,1,10,11,100...1110,1111
Enumerate使用其索引生成y的元组,因此在本例中:

[(0,1),(1,2),(2,3),(3,4)]
(i>>j)&1
部分可能需要一些解释。
(i>>j)
将数字
i
j
向右移位,例如十进制:
4>>2=1
,或二进制:
100>>2=001
&
是按位
运算符。这将检查两个操作数的每一位是否为1,并以数字形式返回结果,就像过滤器一样:
10111&11001=10101


在本例中,它检查位置
j
处的位是否为1。如果是,则将相应的值添加到结果列表中。这样,组合的二进制映射将转换为列表列表,然后返回。

我知道如何运行该函数。我只是不明白如何编写代码来生成一组所有的集合。根据我已经知道的,(I>>j)&1将I的二进制位向右移动j次,然后执行I和1的位和。我不理解所有这些与实际创建结果集的相关性。我知道如何运行函数。我只是不明白如何编写代码来生成一组所有的集合。根据我已经知道的,(I>>j)&1将I的二进制位向右移动j次,然后执行I和1的位和。我不明白所有这些与实际创建结果集的相关性。