0

I'm new to Python, so I might be doing basic errors, so apologies first.

Here is the kind of result I'm trying to obtain :

foo = [
    ["B","C","E","A","D"],
    ["E","B","A","C","D"],
    ["D","B","A","E","C"],
    ["C","D","E","B","A"]
]

So basically, a list of lists of randomly permutated letters without repeat.

Here is the look of what I can get so far :

foo = ['BDCEA', 'BDCEA', 'BDCEA', 'BDCEA']

The main problem being that everytime is the same permutation. This is my code so far :

import random
import numpy as np
letters = ["A", "B", "C", "D", "E"]
nblines = 4
foo = np.repeat(''.join(random.sample(letters, len(letters))), nblines)  

Help appreciated. Thanks

9
  • 1
    I state the result I'm looking for, give the state of my research and code to reproduce... Why vote for closing (at least without explaining) ? -_- Commented Sep 15, 2016 at 13:11
  • Is there any particular reason that you want to do this with Numpy? BTW, the sample foo at the top of your question is a normal Python list of lists, not a Numpy array. Commented Sep 15, 2016 at 13:14
  • @fmalaussena Are repetitions allowed? Could the same string present in the final result more than once? Commented Sep 15, 2016 at 13:23
  • No particular reason, it just so happen that I found this while searching for answers, and thought it could solve my problem. I thought I could transform the Numpy array in a list later. Commented Sep 15, 2016 at 13:24
  • 1
    It's probably a Good Idea to get familiar with core Python (and the major standard libraries that are supplied with it) before attempting to learn Numpy. Commented Sep 15, 2016 at 13:42

3 Answers 3

1

The problem with your code is that the line

foo = np.repeat(''.join(random.sample(letters, len(letters))), nblines)  

will first create a random permutation, and then repeat that same permutation nblines times. Numpy.repeat does not repeatedly invoke a function, it repeats elements of an already existing array, which you created with random.sample.

Another thing is that numpy is designed to work with numbers, not strings. Here is a short code snippet (without using numpy) to obtain your desired result:

[random.sample(letters,len(letters)) for i in range(nblines)]

Result: similar to this:

foo = [
    ["B","C","E","A","D"],
    ["E","B","A","C","D"],
    ["D","B","A","E","C"],
    ["C","D","E","B","A"]
]

I hope this helped ;)

PS: I see that others gave similar answers to this while I was writing it.

Sign up to request clarification or add additional context in comments.

Comments

1

np.repeat repeats the same array. Your approach would work if you changed it to:

[''.join(random.sample(letters, len(letters))) for _ in range(nblines)]
Out: ['EBCAD', 'BCEAD', 'EBDCA', 'DBACE']

This is a short way of writing this:

foo = []
for _ in range(nblines):
    foo.append(''.join(random.sample(letters, len(letters))))

foo
Out: ['DBACE', 'CBAED', 'ACDEB', 'ADBCE']    

3 Comments

Thanks. "this can generate the same sequence" > if you mean that "BCDAE" could appear twice, this is a behaviour I want to be possible. Moreover, do you have a link where I could understand the syntax of this for loop with _, please ? I'm coming from R and I've never seen that.
Yes I meant BCDAE could appear twice. The one with _ is a list comprehension. It is a compact way of writing loops. I used _ as a variable because even though we are iterating over range(nblines) (with 0, 1, 2, 3) we don't need those numbers. We just want to do the same thing 4 times. _ is generally used to indicate that that enumerator is redundant.
Alright, thank you very much. I actually tried the for loop inside the list, but by putting it before the expression and not after, so I wasn't that far.
1

Here's a plain Python solution using a "traditional" style for loop.

from random import shuffle

nblines = 4
letters = list("ABCDE")
foo = []
for _ in range(nblines):
    shuffle(letters)
    foo.append(letters[:])

print(foo)

typical output

[['E', 'C', 'D', 'A', 'B'], ['A', 'B', 'D', 'C', 'E'], ['A', 'C', 'B', 'E', 'D'], ['C', 'A', 'E', 'B', 'D']]

The random.shuffle function shuffles the list in-place. We append a copy of the list to foo using letters[:], otherwise foo would just end up containing 4 references to the one list object.


Here's a slightly more advanced version, using a generator function to handle the shuffling. Each time we call next(sh) it shuffles the lst list stored in the generator and returns a copy of it. So we can call next(sh) in a list comprehension to build the list, which is a little neater than using a traditional for loop. Also, list comprehesions can be slightly faster than using .append in a traditional for loop.

from random import shuffle

def shuffler(seq):
    lst = list(seq)
    while True:
        shuffle(lst)
        yield lst[:]

sh = shuffler('ABCDE')
foo = [next(sh) for _ in range(10)]

for row in foo:
    print(row)

typical output

['C', 'B', 'A', 'E', 'D']
['C', 'A', 'E', 'B', 'D']
['D', 'B', 'C', 'A', 'E']
['E', 'D', 'A', 'B', 'C']
['B', 'A', 'E', 'C', 'D']
['B', 'D', 'C', 'E', 'A']
['A', 'B', 'C', 'E', 'D']
['D', 'C', 'A', 'B', 'E']
['D', 'C', 'B', 'E', 'A']
['E', 'D', 'A', 'C', 'B']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.