0

I have a question. I use combinations to get different combinations from a list. However, if I wish to get a more specific combinations with ascending order(3D,4D,5D), but not (4D,5D,8D), how should I do?

for example:

from itertools import combinations

cards = ["3D", "4D", "5D", "6D"]
comb = []
for j in combinations(cards, 3):
    comb.append(list(j))
for j in combinations(cards, 4)):
    comb.append(list(j))

But I got an output like:

["3D", "4D", "5D"], ["3D", "4D", "6D"], ["3D", "5D", "6D"], ["4D", "5D", "6D"], ["3D", "4D", "5D", "6D"]

how can I get an output like this?

[["3D", "4D", "5D"], ["4D", "5D", "6D"], ["3D", "4D", "5D", "6D"]]
evelyn_7
  • 5
  • 3
  • 1
    those are just slices (or "[chunks](http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python)") of your list. No `itertools `needed. – roippi May 27 '14 at 00:20

2 Answers2

1

Step through the list and zip each 3 consecutive elements together. Then add the complete list of cards at the end.

print ([list(t) for t in zip(*(cards[i:] for i in xrange(3)))]+[cards])
[['3D', '4D', '5D'], ['4D', '5D', '6D'], ['3D', '4D', '5D', '6D']]

If you want to use it on longer lists and group 5 elements together you can change xrange to xrange(5):

cards = ["3D", "4D", "5D", "6D","7D","8D","9D"]
print ([list(t) for t in zip(*(cards[i:] for i in xrange(5)))]+[cards])
[['3D', '4D', '5D', '6D', '7D'], ['4D', '5D', '6D', '7D', '8D'], ['5D', '6D', '7D', '8D', '9D'], ['3D', '4D', '5D', '6D', '7D', '8D', '9D']]

If you card list is not in sorted order you can call the list method sort before you zip like:

cards = ["5D", "6D","3D", "4D"]    
cards.sort()
print [list(t) for t in zip(*(cards[i:] for i in xrange(3)))]+[cards]#
[['3D', '4D', '5D'], ['4D', '5D', '6D'], ['3D', '4D', '5D', '6D']]
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Thanks for that. But if I add one more element, eg. cards.append("8D"). The output would be [['3D', '4D', '5D'], ['4D', '5D', '6D'], ['5D', '6D', '8D'], ['3D', '4D', '5D', '6D', '8D']]. – evelyn_7 May 27 '14 at 02:22
  • you have consecutive numbers in your input list, it is a very different story if you have odd elements, what output do you expect if there are odd elements? – Padraic Cunningham May 27 '14 at 02:38
0

Use the following code:

from itertools import combinations

def check(lst):
        for i in range(len(lst)):
            try:
                    if lst[i+1]-lst[i] != 1:
                            return False
            except IndexError:
                    pass
        return True

cards = ["3D", "4D", "5D", "6D"]
comb = []
for j in combinations(cards, 3):
    comb.append(list(j))
for j in combinations(cards, 4):
    comb.append(list(j))

subs = []
for i in comb:
        subs.append([int(item[0]) for item in i])

subs = [item for item in subs if check(item) == True]

comb = []

for i in subs:
        comb.append([str(item)+'D' for item in i])

print comb

This code converts each sublist to a list of ints using the following code:

>>> item = ['3D', '4D', '6D']
>>> [int(val[0]) for val in item]
[3, 4, 6]
>>> 

We then make sure these numbers are directly ascending:

>>> def check(lst):
...         for i in range(len(lst)):
...             try:
...                     if lst[i+1]-lst[i] != 1:
...                             return False
...             except IndexError:
...                     pass
...         return True
... 
>>> check([3, 4, 6])
False
>>> check([3, 4, 5])
True
>>> check([3, 4, 5, 6])
True
>>> check([3, 4, 5, 8])
False
>>> 

Then using the above logic, we filter everything out, giving the following.

Running:

bash-3.2$ python check.py
[['3D', '4D', '5D'], ['4D', '5D', '6D'], ['3D', '4D', '5D', '6D']]
bash-3.2$ 
A.J. Uppal
  • 19,117
  • 6
  • 45
  • 76
  • Thanks =) for this part: for i in subs: comb.append([str(item)+'D' for item in i]) if there are '6H', '7H', '8H' inside the cards as well, we can't just add 'D'. Any idea on how to fix it? – evelyn_7 May 27 '14 at 03:40
  • You can do `comb.append([str(item)+cards[0][-1] for item in i])`. – A.J. Uppal May 27 '14 at 03:42
  • I see! Nice! What if there are 'JS', 'QS', 'KS' in the cards? We cannot use integer for J, Q and K, right? I have created a dict which assign different numbers to J, Q and K. For example, my_dict = { "J":10, "Q":11, "K":12} Can we arrange it according to the dict? How to do so? – evelyn_7 May 27 '14 at 04:01