Python Forum
Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Simplyfy
#1
The last time I did any coding was about 30 years ago and that was basic. Python seems to have a similar syntax so I thought I would dip my toe in the water again. This code does what it is supposed to ie put every combination of two letters into a list but I'm sure there must be a simpler way. For some reason my variable "c" has been changed to "@" in the copying of my code.


word = "abcde"
twoletter = []
for x in range(0, (len(word)-1)):
     a = word[x]
     b = word[x+1]
     c = a + b
     d = b + a
     twoletter.append(c)
     twoletter.append(d)
     if x + 2 < len(word):
         a = word[x]
         b = word[x + 2]
         c = a + b
         d = b + a
         twoletter.append(c)
         twoletter.append(d)
         if x + 3 < len(word):
             a = word[x]
             b = word[x + 3]
             c = a + b
             d = b + a
             twoletter.append(c)
             twoletter.append(d)
             if x + 4 < len(word):
                 a = word[x]
                 b = word[x + 4]
                 c = a + b
                 d = b + a
                 twoletter.append(c)
                 twoletter.append(d)
Reply
#2
Have a look at itertools module and its itertools.product and itertools.permutations functions.

#! /usr/bin/python3

import itertools
word = "abcde"
# using list comprehension
my_list = [''.join(perm) for perm in itertools.permutations(word,2)]
print (my_list)

# OR using simple llop
my_list = []
for perm in itertools.permutations(word, 2):
   my_list.append(''.join(perm))
print (my_list)
Reply
#3
Itertools is cool to get every combination, or you can also just iterate over the list.

word = "abcde"
twoletter = []
for left in word:
    for right in word:
        if left != right:
            twoletter.append(left + right)
print(twoletter)
# ['ab', 'ac', 'ad', 'ae', 'ba', 'bc', 'bd', 'be', 'ca', 'cb', 'cd', 'ce', 'da', 'db', 'dc', 'de', 'ea', 'eb', 'ec', 'ed']
Reply
#4
Thank you. I knew there had to be an easier and cleaner way. Thanks also to buran for their input.
Reply
#5
As you explore more, you'll pick up more :)
Feel free to come back if you have any other questions, we like helping people :)
Reply
#6
Could not resist the temptation Idea
In [2]: word_set = set('abcde')

In [3]: two_letter = [left + right for right in word_set for left in word_set - set([right])]

In [4]:  print(two_letter)
['ec', 'dc', 'ac', 'bc', 'ce', 'de', 'ae', 'be', 'cd', 'ed', 'ad', 'bd', 'ca', 'ea', 'da', 'ba', 'cb', 'eb', 'db', 'ab']
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#7
Multiple different ways of doing something?  We'd better... run speed tests!!!!

...and something's fishy about the set speed...  I was expecting that to do better.  (that said, they're all close enough that it doesn't matter)

Output:
D:\Projects\playground>python -VV Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] D:\Projects\playground>python temp.py original: 6.258850955969614 nilamo: 4.656287876513283 buran: 4.732732260557226 volcano63: 5.075134360387665 D:\Projects\playground>python temp.py original: 6.198476880215798 nilamo: 4.8221962886350305 buran: 4.808510175991959 volcano63: 5.1591497014125824 D:\Projects\playground>python temp.py original: 6.5075879446218705 nilamo: 4.677959760624388 buran: 4.862944503352491 volcano63: 5.2680807758374115
Testing code:
def original():
   word = "abcde"
   twoletter = []
   for x in range(0, (len(word)-1)):
       a = word[x]
       b = word[x+1]
       c = a + b
       d = b + a
       twoletter.append(c)
       twoletter.append(d)
       if x + 2 < len(word):
           a = word[x]
           b = word[x + 2]
           c = a + b
           d = b + a
           twoletter.append(c)
           twoletter.append(d)
           if x + 3 < len(word):
               a = word[x]
               b = word[x + 3]
               c = a + b
               d = b + a
               twoletter.append(c)
               twoletter.append(d)
               if x + 4 < len(word):
                   a = word[x]
                   b = word[x + 4]
                   c = a + b
                   d = b + a
                   twoletter.append(c)
                   twoletter.append(d)
   return twoletter

def nilamo():
   word = "abcde"
   twoletter = []
   for left in word:
       for right in word:
           if left != right:
               twoletter.append(left + right)
   return twoletter

import itertools
def buran():
   word = "abcde"
   # using list comprehension
   my_list = [''.join(perm) for perm in itertools.permutations(word,2)]
   return my_list

def volcano63():
   word_set = set('abcde')
   two_letter = [left + right for right in word_set for left in word_set - set([right])]
   return two_letter

if __name__ == "__main__":
   import timeit
   for func in ["original", "nilamo", "buran", "volcano63"]:
       print("{0}: {1}".format(func, timeit.timeit("{0}()".format(func), globals=globals())))
Reply
#8
(Apr-30-2017, 08:21 PM)nilamo Wrote: Multiple different ways of doing something?  We'd better... run speed tests!!!!

...and something's fishy about the set speed...  I was expecting that to do better.  (that said, they're all close enough that it doesn't matter)

Set creation is usually comparatively heavy operation - and it's O(n). Also, for each letter in the original word 1-letter set is created - further adding to execution time.

Though I like to occasionally time execution, in this case  my preference for set was certain elegance  Blush (if I say it myself  Shy)

In lookups, set usually give considerable advantage - in that case there's a simple iteration

Since you've vetted my appetite, I tried a slightly different set subtraction method - which gave something like 15% improvement (I did not include set creation in timing)

In [16]: set_sub = lambda ws: [left + right for left in word_set for right in word_set - set([left])]

In [17]: set_diff = lambda ws:  [left + right for left in ws for right in ws.difference(left)]

In [18]: %timeit set_sub(word_set)
100000 loops, best of 3: 5.38 µs per loop

In [19]: %timeit set_diff(word_set)
100000 loops, best of 3: 4.58 µs per loop
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020