0

I have a list of words named words and I would like to generate a list of 100 three-words elements named pwds. I want these 3 words to be randomly picked from the words list for each element of the pwds list, and I'd like to use list comprehension to do this.

This solution works :

pwds = [random.choice(words)+' '+random.choice(words)+' '+random.choice(words) for i in range(0,100)]

It generates a list that looks like : ['correct horse battery', 'staple peach peach', ...]

But I was looking for a way that prevents repetiting 3 times random.choice(words), so I tried this :

pwds = [(3*(random.choice(words)+' ')).strip() for i in range(0,100)]

But unfortunately, this solution makes each element having the same word three times (for example : ['horse horse horse', 'staple staple staple', ...]), which is expected to happend.

Do you know a way to pick 3 random words without repetition (EDIT : by "repetition", I mean the code repetition, not the random words repetition) ?

EDIT : My question is different than the one it has been marked as duplicate of because I'm looking for using list comprehension here. I know how I could generate different numbers, I'm just looking for specific way to do it.

Seeven
  • 969
  • 1
  • 8
  • 24
  • 1
    [`random.sample`](https://docs.python.org/2/library/random.html#random.sample)? – jonrsharpe Aug 29 '14 at 09:20
  • @jonrsharpe: This function is great, I came up with this solution : `pwds = [' '.join(random.sample(words,3)) for i in range(0,100)]`. But this function prevents the possibility that the same word occurs 2 or 3 times in the same element. – Seeven Aug 29 '14 at 09:30

2 Answers2

2

If you want the words to be able to repeat within each triplet, I think what you want is something like:

pwds = [" ".join(random.choice(words) for _ in range(3)) for _ in range(100)]

Note the use of _ to indicate that we don't actually use the numbers generated by either range, and the fact that range(0, n) is the same as range(n).

A somewhat shorter example:

>>> import random
>>> words = ['correct', 'horse', 'battery', 'staple']
>>> [" ".join(random.choice(words) for _ in range(3)) for _ in range(5)]
['horse horse correct', 
 'correct staple staple', 
 'correct horse horse', 
 'battery staple battery', 
 'horse battery battery']
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
1

You can use the join function and a list comprehension to not repeat random.choice

pwds = [' '.join([random.choice(words) for _ in range(3)]) for _ in range(100)]
Gabz
  • 124
  • 3
  • Although it is the same answer than jonrsharpe, yours helps to understand that we are using a nested list comprehension, which I didn't understand at first. – Seeven Aug 29 '14 at 09:55
  • Absolutly, jonrsharpe was just faster than me. – Gabz Aug 29 '14 at 09:58
  • 1
    Actually, this is slightly better than my approach, as passing a list (rather than the bare generator expression) to `str.join` is more efficient - see http://stackoverflow.com/a/9061024/3001761 – jonrsharpe Aug 29 '14 at 10:39
  • @SeevenByakko no problem. It won't make much difference with three items, but it's worth knowing about. – jonrsharpe Aug 29 '14 at 11:07