Generate combinations of elements from multiple li

2019-09-18 02:57发布

问题:

I'm making a function that takes a variable number of lists as input (i.e., an arbitrary argument list). I need to compare each element from each list to each element of all other lists, but I couldn't find any way to approach this.

回答1:

The itertools module provides a lot of useful tools just for such tasks. You can adapt the following example to your task by integrating it into your specific comparison logic.

Note that the following assumes a commutative function. That is, about half of the tuples are omitted for reasons of symmetry.

Example:

import itertools

def generate_pairs(*args):
    # assuming function is commutative
    for i, l in enumerate(args, 1):
        for x, y in itertools.product(l, itertools.chain(*args[i:])):
            yield (x, y)

# you can use lists instead of strings as well
for x, y in generate_pairs("ab", "cd", "ef"):
    print (x, y)

# e.g., apply your comparison logic
print any(x == y for x, y in generate_pairs("ab", "cd", "ef"))
print all(x != y for x, y in generate_pairs("ab", "cd", "ef"))

Output:

$ python test.py
('a', 'c')
('a', 'd')
('a', 'e')
('a', 'f')
('b', 'c')
('b', 'd')
('b', 'e')
('b', 'f')
('c', 'e')
('c', 'f')
('d', 'e')
('d', 'f')
False
True


回答2:

Depending on your goal, you can make use of some of the itertools utilities. For example, you can use itertools.product on *args:

from itertools import product
for comb in product(*args):
    if len(set(comb)) < len(comb):
        # there are equal values....

But currently it's not very clear from your question what you want to achieve. If I didn't understand you correctly, you can try to state the question in a more specific way.



回答3:

I think @LevLeitsky's answer is the best way to do a loop over the items from your variable number of lists. However, if purpose the loop is just to find common elements between pairs of items from the lists, I'd do it a bit differently.

Here's an approach that finds the common elements between each pair of lists:

import itertools

def func(*args):
    sets = [set(l) for l in args]
    for a, b in itertools.combinations(sets, 2):
        common = a & b # set intersection
        # do stuff with the set of common elements...

I'm not sure what you need to do with the common elements, so I'll leave it there.



回答4:

if you want the arguments as dictionary

def kw(**kwargs):
    for key, value in kwargs.items():
        print key, value

if you want all the arguments as list:

 def arg(*args):
        for item in args:
            print item

you can use both

def using_both(*args, **kwargs) :
     kw(kwargs)
     arg(args)

call it like that:

using_both([1,2,3,4,5],a=32,b=55)