0

I need some help. I check, there are few questions about 'counting permutations', but I didn't find an answer suitable for my case.

I would like to count the total number of permutations of each item in a list of items. Say, you have two lists ('first', 'second' see below) and for each element of 'first', I would like to have its total number of unique permutations. e.g for 'a' in 'first' we have

ab ac ad ab ac ad ab ab

by removing duplicates, we have

ab ac ad

So the number of permutations of 'a' will be '3'

The final result I would like to get should be like

(a, 3)

(b, 3)

(c, 3)

(d, 3)

I start with

import itertools
from collections import Counter
first = ['a','b','c','d']
second = [['a','b','c','d'], ['a','b'], ['a','c','d'], ['a','b','d']]
c = Counter()
for let in second:
      letPermut = list(set(itertools.permutations(let, 2)))
      for i in first:
          for permut in letPermut:
                 if permut[0] == i:
                        c[i] += 1
      for item in c.items():
          print(item)

But in the output I get different counts for each element in first list, and the Counter's results are higher than the expected output. I don't know what I am doing wrong.

Any help?

Community
  • 1
  • 1
dcpula
  • 29
  • 6
  • Your question doesn't make sense. You want to remove duplicates but when you show your desired output it has 3 b's 3 c's and 3 d's when there's only one of each after duplicates are removed – SirParselot Feb 11 '16 at 14:56
  • I also don't understand what you are trying to do. I can't see in your text description what is the role of the second list. Please write the inputs directly as python code, and the expected output. – bgusach Feb 11 '16 at 15:01
  • If you do a permutation of `[a,b,c,d]` you will not get `ab ac ad ab ac ad ab ab` for all the ones with `a`. There's an extra pair in there and half of them won't start with `a`. However, you will get `ab ac ad ba ca da`. Are you looking for the combinations? – SirParselot Feb 11 '16 at 15:05
  • for each element of 'first' that **also** appears in any sublist of 'second', I would like to count its total number of pemutations, **without duplicates**. That means if there `ac ac` it counts ONE. Hope is clear now – dcpula Feb 11 '16 at 15:34
  • SirParselot is just trying to verify whether `ac ca` counts as one (comination) or two (permutations). – jpaugh Feb 11 '16 at 17:51
  • For what I was interested in, `ac ca` counts as two permutations – dcpula Feb 11 '16 at 18:06

2 Answers2

2

Well, the question is still not very clear, but here my 0.02$:

def do_the_stuff(first, second):
    second = list(set(second))

    return {
        el1: sum(1 for el2 in second if el1 in el2)
        for el1 in first
    }

With some test data:

>>> first = ['a','b','c','d', 'j']
>>> second = ['abcd', 'ab', 'ab', 'acd', 'abd']
>>> print do_the_stuff(first, second)
{'a': 4, 'c': 2, 'b': 3, 'd': 3, 'j': 0}       
bgusach
  • 14,527
  • 14
  • 51
  • 68
  • That could be a good starting point for me. Unless I miss something, I would expect `{'a': 3, 'c': 3, 'b': 3, 'd': 3, 'j': 0} ` – dcpula Feb 11 '16 at 16:10
  • `a` is in `abcd`, `ab`, `acd` and `abd`, therefore count is `4`. Same for `c`. I think it matches your spec. My input data is not the same as your example, maybe you just mixed them. – bgusach Feb 11 '16 at 17:00
  • Thanks. I have just got an answer (see above) that is solving my problem – dcpula Feb 11 '16 at 17:05
  • Not to sound egocentric, but if it works as expected you should mark mine: it came first and it is quite more elegant and efficient – bgusach Feb 11 '16 at 17:07
  • Hope you aren't disappointed in me. Your answer is useful, but it didn't solve the problem – dcpula Feb 11 '16 at 17:16
  • It's all right. However, I would recommend you to improve your communication skills, it was hard to understand what exactly you meant. Cheers. – bgusach Feb 11 '16 at 17:18
  • 1
    @dcpula: bgusach is right. I made some edits to your question to improve readability (if you agree, the edition will be committed). I suggest you to read [How to ask a good question](http://stackoverflow.com/help/how-to-ask) to see tips to make questions more readable. You are also welcome to take a look in the [Help Center](http://stackoverflow.com/help/) to learn more about how StackOverflow works. – SebasSBM Feb 11 '16 at 17:24
  • Yes, please make commit. Sorry, I am a new user, I registered last week. I'll manage to do better next time – dcpula Feb 11 '16 at 17:33
  • I already made the edit, but it won't be published until you review and confirm the edition. – SebasSBM Feb 11 '16 at 17:42
  • Thanks. Can you tell me where I can review it and confirm the edition? – dcpula Feb 11 '16 at 17:50
1

If I did understand well your problem, these changes make your code ignore duplicate permutations:

import itertools
from collections import Counter
first = ['a','b','c','d']
second = [['a','b','c','d'], ['a','b'], ['a','c','d'], ['a','b','d']]
uniques = []
c = Counter()
for let in second:
    letPermut = list(set(itertools.permutations(let, 2)))
    for i in first:
        for permut in letPermut:
            if permut[0] == i and not permut in uniques:
                c[i] += 1
                uniques.append(permut)
for item in c.items():
    print(item)

The changes:

  • Declare an empty list called uniques
  • We check against uniques if permutation is a duplicate before counting +1
  • After increasing the counter we add the permutation to uniques for future check
  • Took the printing loop out of the for let in second loop. Thus, each counter is only printed once at the end.
SebasSBM
  • 860
  • 2
  • 8
  • 32
  • Yes it should be something like that. But it gives each result three times. It gives `('c', 3) ('a', 3) ('b', 3) ('d', 3) ('c', 3) ('a', 3) ('b', 3) ('d', 3) ('c', 3) ('a', 3) ('b', 3) ('d', 3) ('c', 3) ('a', 3) ('b', 3) ('d', 3)`. The final output should be `('a', 3) ('b',3) ('c',3) ('d',3)` – dcpula Feb 11 '16 at 16:43
  • Keep in mind that I removed one identation level for the last two lines. This takes those two lines out of the first loop to prevent the error you commented, as explained in my answer. – SebasSBM Feb 11 '16 at 16:45
  • You are right. Sorry I wasn't careful to the indentation. It works perfectly. Thank for you help – dcpula Feb 11 '16 at 17:02