1

I am trying to write a python 3.6 command-line program that accepts as arguments one or more lists and then returns the cartesian product of those lists, possibly in deduplicated form.

I have it working correctly with one and two list arguments, but I cannot figure out how to make the program correctly handle three or more arguments.

The desired output is the cartesian product that includes every list passed as an argument on the command line.

This is the code I have so far:

def createArgumentParser():

    from argparse import ArgumentParser

    __parser = ArgumentParser()
    __parser.add_argument("list", type=list, nargs="+", help="List(s) to compute the cartesian product of")
    __parser.add_argument("-u", "--unique", action="store_true", help="Deduplicate lists so that they become sets of unique elements")
    __parser.add_argument("-U", "--Universally_unique", action="store_true", help="Deduplicate the resulting cartesian product so that the final result is a set of unique elements")
    return __parser.parse_args()


def cartesianProduct(__unique, __Universally_unique, *__list):

    from itertools import product

    __cartesianProduct = product([])

    if __unique:
        __cartesianProduct = product(sorted(set(__list[0])), sorted(set(__list[len(__list)-1])))
    else:
        __cartesianProduct = product(__list[0], __list[len(__list)-1])
    if __Universally_unique:
        __cartesianProduct = sorted(set(__cartesianProduct))
        for __element in __cartesianProduct:
            if __element[0] == __element[1]:
            __cartesianProduct.remove(__element)
    return __cartesianProduct


def main():

    __args = createArgumentParser()

    for __element in cartesianProduct(__args.unique, __args.Universally_unique, *__args.list):
        print(__element)

Running the program with the command line arguments abc 123 def returns this:

('a', 'd')
('a', 'e')
('a', 'f')
('b', 'd')
('b', 'e')
('b', 'f')
('c', 'd')
('c', 'e')
('c', 'f')

The 123 part is missing from the cartesian product. How can I fix that?

  • Please first correct your format. – Sraw Oct 11 '17 at 03:33
  • 1
    Do you really need so many `__` variables? It kills readability. – cs95 Oct 11 '17 at 03:33
  • 1
    I was expecting backlash about my coding style. I am self taught and a total beginner. However, for me the underscores aid readability in various ways (as weird as it may sound). I am not collaborating with anyone on this project so I didn't see the need for a more standard style. I will keep in mind that others find it annoying. –  Oct 11 '17 at 03:37
  • Please don't use double underscore names unless you _really_ need name mangling. And if you're not sure whether you _need_ name mangling or not, you don't need it. Please see [What is the meaning of a single- and a double-underscore before an object name?](https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-a-single-and-a-double-underscore-before-an-object-name) – PM 2Ring Oct 11 '17 at 03:50
  • 1
    Also, don't bury `import` statements inside your functions, put them at the top of the script, where they belong. I suggest you take a look at [PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008) – PM 2Ring Oct 11 '17 at 03:53
  • Thank you PM 2Ring, I will have a look. –  Oct 11 '17 at 04:01

1 Answers1

1

To get the Cartesian product of all items of a list you can use the * operator to perform argument unpacking. This is sometimes known as "splat" unpacking.

from itertools import product

src = ['abc', '123',  'def']
cartesian_product = [''.join(t) for t in product(*src)]
print(cartesian_product)

output

['a1d', 'a1e', 'a1f', 'a2d', 'a2e', 'a2f', 'a3d', 'a3e', 'a3f', 'b1d', 'b1e', 'b1f', 'b2d', 'b2e', 'b2f', 'b3d', 'b3e', 'b3f', 'c1d', 'c1e', 'c1f', 'c2d', 'c2e', 'c2f', 'c3d', 'c3e', 'c3f']
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • Thanks! I figured it would be something simple I wasn't getting. This does the trick. –  Oct 11 '17 at 04:23