0

What I have so far does pretty much nothing

def dress_me(shirt, tie, suit):


 #    if type(shirt) != list or type(tie) != list or type(suit) != list:
    #        return None
            combinations = dress_me(shirt, tie, suit)
            for combo in combinations:
                print(combo)
Shankar Narayana Damodaran
  • 68,075
  • 43
  • 96
  • 126
Zaid Haddadin
  • 31
  • 1
  • 2

4 Answers4

4

Use itertools.product:

def dress_me(shirt, tie, suit):
    if type(shirt) != list or type(tie) != list or type(suit) != list:
        return None
    return list(itertools.product(shirt, tie, suit))

Demo:

>>> dress_me([1,2,3],[4,5,6],[7,8,9])
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 6, 7), (1, 6, 8), (1, 6, 9), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 6, 7), (2, 6, 8), (2, 6, 9), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 6, 7), (3, 6, 8), (3, 6, 9)]
zhangyangyu
  • 8,520
  • 2
  • 33
  • 43
  • 3
    I think it would be more Pythonic if there were no list test. Any iterable would actually work. I'm not sure it makes a whole lot of sense to return `None` if one of the inputs is invalid; that seems counter-intuitive. I'd expect an exception if I passed it a non-iterable; it would make tracking my problem down easier. If returning `None` is actually required, then see [this answer](http://stackoverflow.com/a/4668647/1394393) for checking for iterable types. – jpmc26 Aug 08 '13 at 06:58
  • Yes. What you say is reasonable. But first I just answer the question the OP seems to want. And then test if is Iterable is no good. What if a string is passed? I would lead to error. try...except is a good choice. I like that too. – zhangyangyu Aug 08 '13 at 07:04
  • 2
    A string is an iterable; you'd get a product of all the characters, which might be exactly what the caller wants. (I checked, and the answer I linked works for strings, at least in 2.7.) I would assume that the programmer calling the function is aware that strings are iterable, and if it's not the output they wanted, they'll see that very quickly. – jpmc26 Aug 08 '13 at 07:09
  • If a string is passed, what you get is apprently not the OP wants. – zhangyangyu Aug 08 '13 at 07:11
1

Or, for completeness, in the generator-fashion without an extra function:

import itertools

for combination in itertools.product(shirts, ties, suits):
    whatever_you_want_to_do(combination)
sebastian
  • 9,526
  • 26
  • 54
0
def dress_me(shirt, tie, suit):
    all_combinations = []
    for s in shirt:
        for t in tie:
            for su in suit:
                all_combinations.append((s,t,su))
    return all_combination

Maybe there is a more pythonic way to do it :)

Neaţu Ovidiu Gabriel
  • 833
  • 3
  • 10
  • 20
0

Since it looks like you were trying to come up with a recursive solution, here is the general form of it:

def all_perms(thing):
    if len(thing) <=1:
        yield thing
    else:
        for perm in all_perms(thing[1:]):
            for i in range(len(perm)+1):
                yield perm[:i] + thing[0:1] + perm[i:]

This works for most kinds of iterables. Demo:

In [5]: list(all_perms(('shirt','tie','suit')))
Out[5]: 
[('shirt', 'tie', 'suit'),
 ('tie', 'shirt', 'suit'),
 ('tie', 'suit', 'shirt'),
 ('shirt', 'suit', 'tie'),
 ('suit', 'shirt', 'tie'),
 ('suit', 'tie', 'shirt')]

Recursion is difficult to understand at first, but the general form is:

if simplest_case:
    return simplest_case
else:
    #recurse

In this case, return is replaced by yield in order to make a generator, which is more memory-friendly. You still shouldn't expect this to be the best-performing solution, but I'm including it for completeness since "USE ITERTOOLS" doesn't end up teaching you much other than itertools is cool.

roippi
  • 25,533
  • 4
  • 48
  • 73