对列表中的每对元素进行操作

发布于 2024-07-23 05:37:08 字数 263 浏览 6 评论 0原文

我想使用 Python 比较列表中的每个可能的对。

假设我

my_list = [1,2,3,4]

想对列表中 2 个元素的每个组合执行一个操作(我们称之为 foo)。

相同,但这看起来不太Pythonic。

foo(1,1)
foo(1,2)
...
foo(4,3)
foo(4,4)

最终结果应该与我的第一个想法是手动迭代列表两次

Using Python, I'd like to compare every possible pair in a list.

Suppose I have

my_list = [1,2,3,4]

I'd like to do an operation (let's call it foo) on every combination of 2 elements from the list.

The final result should be the same as

foo(1,1)
foo(1,2)
...
foo(4,3)
foo(4,4)

My first thought was to iterate twice through the list manually, but that doesn't seem very pythonic.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

如果没有你 2024-07-30 05:37:08

查看 product() 中的 <代码>itertools模块。 它的作用正是你所描述的。

import itertools

my_list = [1,2,3,4]
for pair in itertools.product(my_list, repeat=2):
    foo(*pair)

这相当于:

my_list = [1,2,3,4]
for x in my_list:
    for y in my_list:
        foo(x, y)

编辑:还有两个非常相似的函数,permutations()combinations()。 为了说明它们有何不同:

product() 生成所有可能的元素配对,包括所有重复项:

1,1  1,2  1,3  1,4
2,1  2,2  2,3  2,4
3,1  3,2  3,3  3,4
4,1  4,2  4,3  4,4

permutations() 生成每个唯一元素对的所有唯一排序,从而消除了x,x 重复:

 .   1,2  1,3  1,4
2,1   .   2,3  2,4
3,1  3,2   .   3,4
4,1  4,2  4,3   .

最后,combinations() 仅按字典顺序生成每个唯一的元素对:

 .   1,2  1,3  1,4
 .    .   2,3  2,4
 .    .    .   3,4
 .    .    .    .

所有这三个函数都是在 Python 2.6 中引入的。

Check out product() in the itertools module. It does exactly what you describe.

import itertools

my_list = [1,2,3,4]
for pair in itertools.product(my_list, repeat=2):
    foo(*pair)

This is equivalent to:

my_list = [1,2,3,4]
for x in my_list:
    for y in my_list:
        foo(x, y)

Edit: There are two very similar functions as well, permutations() and combinations(). To illustrate how they differ:

product() generates every possible pairing of elements, including all duplicates:

1,1  1,2  1,3  1,4
2,1  2,2  2,3  2,4
3,1  3,2  3,3  3,4
4,1  4,2  4,3  4,4

permutations() generates all unique orderings of each unique pair of elements, eliminating the x,x duplicates:

 .   1,2  1,3  1,4
2,1   .   2,3  2,4
3,1  3,2   .   3,4
4,1  4,2  4,3   .

Finally, combinations() only generates each unique pair of elements, in lexicographic order:

 .   1,2  1,3  1,4
 .    .   2,3  2,4
 .    .    .   3,4
 .    .    .    .

All three of these functions were introduced in Python 2.6.

南城旧梦 2024-07-30 05:37:08

我遇到了类似的问题,并在此处找到了解决方案。 它无需导入任何模块即可工作。

假设一个列表如下:

people = ["Lisa","Pam","Phil","John"]

简化的单行解决方案如下所示。

所有可能的对,包括重复项:

result = [foo(p1, p2) for p1 in people for p2 in people]

所有可能的对,不包括重复项

result = [foo(p1, p2) for p1 in people for p2 in people if p1 != p2]

唯一对,其中顺序无关:

result = [foo(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]

如果您不想要操作但只是为了获取对,删除函数 foo 并仅使用元组就足够了。

所有可能的对,包括重复项:

list_of_pairs = [(p1, p2) for p1 in people for p2 in people]

结果:

('Lisa', 'Lisa')
('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Lisa')
('Pam', 'Pam')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'Lisa')
('Phil', 'Pam')
('Phil', 'Phil')
('Phil', 'John')
('John', 'Lisa')
('John', 'Pam')
('John', 'Phil')
('John', 'John')

所有可能的对,不包括重复项

list_of_pairs = [(p1, p2) for p1 in people for p2 in people if p1 != p2]

结果:

('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Lisa')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'Lisa')
('Phil', 'Pam')
('Phil', 'John')
('John', 'Lisa')
('John', 'Pam')
('John', 'Phil')

唯一对,其中顺序无关:

list_of_pairs = [(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]

结果:

('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'John')

< em>编辑:在重新设计以简化此解决方案后,我意识到它与 Adam Rosenfield 的方法相同。 我希望更详细的解释可以帮助一些人更好地理解它。

I had a similar problem and found the solution here. It works without having to import any module.

Supposing a list like:

people = ["Lisa","Pam","Phil","John"]

A simplified one-line solution would look like this.

All possible pairs, including duplicates:

result = [foo(p1, p2) for p1 in people for p2 in people]

All possible pairs, excluding duplicates:

result = [foo(p1, p2) for p1 in people for p2 in people if p1 != p2]

Unique pairs, where order is irrelevant:

result = [foo(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]

In case you don't want to operate but just to get the pairs, removing the function foo and using just a tuple would be enough.

All possible pairs, including duplicates:

list_of_pairs = [(p1, p2) for p1 in people for p2 in people]

Result:

('Lisa', 'Lisa')
('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Lisa')
('Pam', 'Pam')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'Lisa')
('Phil', 'Pam')
('Phil', 'Phil')
('Phil', 'John')
('John', 'Lisa')
('John', 'Pam')
('John', 'Phil')
('John', 'John')

All possible pairs, excluding duplicates:

list_of_pairs = [(p1, p2) for p1 in people for p2 in people if p1 != p2]

Result:

('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Lisa')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'Lisa')
('Phil', 'Pam')
('Phil', 'John')
('John', 'Lisa')
('John', 'Pam')
('John', 'Phil')

Unique pairs, where order is irrelevant:

list_of_pairs = [(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]

Result:

('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'John')

Edit: After the rework to simplify this solution, I realised it is the same approach than Adam Rosenfield. I hope the larger explanation helps some to understand it better.

茶色山野 2024-07-30 05:37:08

如果您只是调用一个函数,那么您实际上不能做得比以下更好:

for i in my_list:
    for j in my_list:
        foo(i, j)

如果您想收集调用该函数的结果列表,您可以这样做:

[foo(i, j) for i in my_list for j in my_list]

这将返回应用 < 的结果列表code>foo(i, j) 到每个可能的对 (i, j)

If you're just calling a function, you can't really do much better than:

for i in my_list:
    for j in my_list:
        foo(i, j)

If you want to collect a list of the results of calling the function, you can do:

[foo(i, j) for i in my_list for j in my_list]

which will return you a list of the result of applying foo(i, j) to each possible pair (i, j).

流绪微梦 2024-07-30 05:37:08
my_list = [1,2,3,4]

pairs=[[x,y] for x in my_list for y in my_list]
print (pairs)
my_list = [1,2,3,4]

pairs=[[x,y] for x in my_list for y in my_list]
print (pairs)
云仙小弟 2024-07-30 05:37:08

如果您希望组合按字典顺序排序,Ben Bank 的答案效果很好。 但是,如果您希望组合随机排序,这里有一个解决方案:

import random
from math import comb


def cgen(i,n,k):
    """
    returns the i-th combination of k numbers chosen from 0,1,...,n-1
    
    forked from: https://math.stackexchange.com/a/1227692
    changed from 1-indexed to 0-indexed.
    """
    # 1-index
    i += 1
    
    c = []
    r = i+0
    j = 0
    for s in range(1,k+1):
        cs = j+1
        while r-comb(n-cs,k-s)>0:
            r -= comb(n-cs,k-s)
            cs += 1
        c.append(cs-1)
        j = cs
    return c


def generate_random_combinations(n, k, shuffle=random.shuffle):
    """
    Generate combinations in random order of k numbers chosen from 0,1,...,n-1.
    
    :param shuffle: Function to in-place shuffle the indices of the combinations. Use for seeding.
    """
    total_combinations = comb(n, k)
    combination_indices = list(range(total_combinations))
    shuffle(combination_indices)
    
    for i in combination_indices:
        yield cgen(i, n, k)

示例用法

N=100k=4

gen_combos = generate_random_combinations(100, 4)

for i in range(3):
    print(next(gen_combos))

:结果为:

[4, 9, 55, 79]
[11, 49, 58, 64]
[75, 82, 83, 91]

用例

对于我的用例,我正在实现一种算法,该算法正在搜索单个(或几个)组合,并在找到有效组合时停止。 平均而言,它遍历所有可能组合的一个非常小的子集,因此不需要预先构建所有可能的组合,然后进行洗牌(无论如何,总体规模太大,无法容纳内存中的所有组合)。

随机性对于快速找到解决方案至关重要,因为字典顺序会导致总体中的单个值包含在所有组合中,直到耗尽为止。 例如,如果我们有 n=100k=4,那么结果将类似于:

索引组合
0(0, 1, 2, 3)
1(0 , 1, 2, 4)
2(0, 1, 2, 5)
...
156848(0, 97, 98, 99)
156849(1, 2, 3, 4)

如果 0 不是有效解的一部分,那么我们将无缘无故地搜索 156849 个组合。 随机化顺序有助于缓解此问题(请参阅上面的示例输出)。

Ben Bank's answer works well if you want the combinations to be ordered lexicographically. However, if you want the combinations to be randomly ordered, here's a solution:

import random
from math import comb


def cgen(i,n,k):
    """
    returns the i-th combination of k numbers chosen from 0,1,...,n-1
    
    forked from: https://math.stackexchange.com/a/1227692
    changed from 1-indexed to 0-indexed.
    """
    # 1-index
    i += 1
    
    c = []
    r = i+0
    j = 0
    for s in range(1,k+1):
        cs = j+1
        while r-comb(n-cs,k-s)>0:
            r -= comb(n-cs,k-s)
            cs += 1
        c.append(cs-1)
        j = cs
    return c


def generate_random_combinations(n, k, shuffle=random.shuffle):
    """
    Generate combinations in random order of k numbers chosen from 0,1,...,n-1.
    
    :param shuffle: Function to in-place shuffle the indices of the combinations. Use for seeding.
    """
    total_combinations = comb(n, k)
    combination_indices = list(range(total_combinations))
    shuffle(combination_indices)
    
    for i in combination_indices:
        yield cgen(i, n, k)

Example Usage

For N=100 and k=4:

gen_combos = generate_random_combinations(100, 4)

for i in range(3):
    print(next(gen_combos))

results in:

[4, 9, 55, 79]
[11, 49, 58, 64]
[75, 82, 83, 91]

Use Case

For my use case, I'm implementing an algorithm that's searching for a single (or a few) combination and halts when it finds a valid combination. On average, it traverses a very small subset of all possible combinations, so there's no need to build all possible combinations up front and then shuffle (the population size is too big to fit all combinations in memory, anyway).

The randomness is crucial to finding a solution quickly because lexicographic ordering results in a single value in the population being included in all combinations until it's exhausted. For example, if we have n=100 and k=4, then the results will be like:

indexcombination
0(0, 1, 2, 3)
1(0, 1, 2, 4)
2(0, 1, 2, 5)
...
156848(0, 97, 98, 99)
156849(1, 2, 3, 4)

If 0 is not part of a valid solution, then we will have searched 156849 combinations for no reason. Randomizing the order helps mitigate this issue (see example output above).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文