list of list random shuffle in Python? - python

I'm trying to get a list of randomized element inside a list. Something like this:
[['3','1','2','4'],
['2','1','3','4'],
['3','1','2','4'],
['4','1','3','2']]
Each row shall contain randomly shuffled elements of 1,2,3,4, so I thought to reshuffle it few times.
I have used the following [yes, could be in loop, but that is more clear I hope]:
import random
p1=['1','2','3','4']
p=[]
random.shuffle(p1)
p.append(p1)
print p
random.shuffle(p1)
p.append(p1)
print p
random.shuffle(p1)
p.append(p1)
print p
random.shuffle(p1)
p.append(p1)
print p
However the result was like that:
>>>
[['2', '4', '1', '3']]
[['3', '4', '1', '2'], ['3', '4', '1', '2']]
[['2', '4', '3', '1'], ['2', '4', '3', '1'], ['2', '4', '3', '1']]
[['1', '3', '4', '2'], ['1', '3', '4', '2'], ['1', '3', '4', '2'], ['1', '3', '4', '2']]
What I've made wrong? How to do that simple task in proper way?

You're appending the same p1 object you keep modifying. Rather, append a copy! I.e, change each
p.append(p1)
into
p.append(list(p1))

Related

How to retrieve the position of a list in a list of lists in python

A = [['0', '6', '4', '3'], ['0', '2', '8', '3'], ['0', '4', '1', '5'], ['0', '3', '2', '5']]
B = ['0', '4', '1', '5']
Say I want to find out at which line does B equal to the list. How do I write a solution for this?
The answer would be the third line.
I tried doing a for loop.
You can try list.index(element) to get the index of the element in the original list (A). In your terminology, to get the line just add one to the index.
line = A.index(B) + 1
you dont need use loops.you can get the element index by indexing.
A = [['0', '6', '4', '3'], ['0', '2', '8', '3'], ['0', '4', '1', '5'], ['0', '3', '2', '5']]
B = ['0', '4', '1', '5']
print(A.index(B))
>>> 2

Sample from list of lists until condition is met

I have a list of lists that I am randomly choosing a value from. The issue I am having now is that since the loop I wrote is using random.choice() there is the possibility that a given value won't be present, which will cause an error in downstream code. So I basically want to sample from this list of lists until the final list has at least one occurrence of each value (so at least one occurrence of 1-8).
Below is my current code and the output list for probe which doesn't include a single occurrence of 3 in this iteration, which will cause the subsequent code to fail.
Some restrictions I have:
The final list probe needs to be only 16 items.
One of the two values needs to be picked at each index because it codes for a later stimulus. So for example, probe[0] in this case needs to be either 7 or 6 and probe[15] needs to be either 3 or 2. But still with the condition that across all indexes, 1-8 appears at least once.
probe_list = [['7', '6'], ['5', '8'], ['3', '2'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['7', '6'], ['1', '4'], ['3', '2'], ['7', '6'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['3', '2']]
probe=[]
for i in range(len(probe_list)):
choose = random.choice(probe_list[i])
probe.append(choose)
probe = ['7', '8', '2', '1', '6', '1', '5', '6', '4', '2', '7', '4', '6', '4', '8', '2']
You could create a set, which contains all values which are already in the probe in the current "run". Then you could always check, whether the size of the set is 8. If you begin a new "run", then you have to clear() the set and the probe.
import random
probe_list = [['7', '6'], ['5', '8'], ['3', '2'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['7', '6'], ['1', '4'], ['3', '2'], ['7', '6'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['3', '2']]
probe=[]
while True:
contained=set()
probe = []
for i in range(len(probe_list)):
choose = random.choice(probe_list[i])
contained.add(choose)
probe.append(choose)
if len(contained) == 8:
break
print(probe, len(probe), len(set(probe)))
It would alway ensure, that the length of the probe is 16 and the number of unique items in the probe is 8.
For example the output:
['7', '5', '2', '4', '6', '1', '8', '7', '1', '3', '6', '4', '6', '1', '5', '3'] 16 8

How can I check if number exists in list

I wish to check if a certain number is in a list, but I'm struggling with the if sentence. I have
possibilities = []
node = 1
edges = [['1', '1', '10'], ['1', '6', '7'], ['1', '16', '5'], ['1', '18', '6'], ['1', '19', '6'], ['2', '2', '10'], ['2', '5', '3']]
for i in edges:
if node in i[:-1]:
possibilities.append(i)
print(possibilities)
But I'm not getting any entries in possibilities. Is there something I'm missing, because I thought this should work.
You are confusing the data type int with data type string. Change the node to "1" instead of 1 and you are good to go.
You are trying to compare int data type with str data type. Try this:
possibilities = []
node = 1
edges = [['1', '1', '10'], ['1', '6', '7'], ['1', '16', '5'], ['1', '18', '6'], ['1', '19', '6'], ['2', '2', '10'], ['2', '5', '3']]
for i in edges:
if str(node) in i:
possibilities.append(i)
print(possibilities)

How to find all possible combinations from nested list containing list and strings?

I am trying to get all possible pattern from list like:
input_x = ['1', ['2', '2x'], '3', '4', ['5', '5x']]
As we see, it has 2 nested list ['2', '2x'] and ['5', '5x'] here.
That means all possible pattern is 4 (2 case x 2 case), the expect output is:
output1 = ['1','2' , '3', '4', '5']
output2 = ['1','2x', '3', '4', '5']
output3 = ['1','2' , '3', '4', '5x']
output4 = ['1','2x', '3', '4', '5x']
I tried to search how to, but I can not find any examples (because of I have no idea about "keyword" to search)
I think python has inner libraries/methods to handle it.
One way to achieve this is via using itertools.product. But for using that, you need to firstly wrap the single elements within your list to another list.
For example, firstly we need to convert your list:
['1', ['2', '2x'], '3', '4', ['5', '5x']]
to:
[['1'], ['2', '2x'], ['3'], ['4'], ['5', '5x']]
This can be done via below list comprehension as:
formatted_list = [(l if isinstance(l, list) else [l]) for l in my_list]
# Here `formatted_list` is containing the elements in your desired format, i.e.:
# [['1'], ['2', '2x'], ['3'], ['4'], ['5', '5x']]
Now call itertools.product on the unpacked version of the above list:
>>> from itertools import product
# v `*` is used to unpack the `formatted_list` list
>>> list(product(*formatted_list))
[('1', '2', '3', '4', '5'), ('1', '2', '3', '4', '5x'), ('1', '2x', '3', '4', '5'), ('1', '2x', '3', '4', '5x')]
If you don't want to convert your list to all sub list then
You can try something like this :
input_x = ['1', ['2', '2x'], '3', '4', ['5', '5x'],['6','6x']]
import itertools
non_li=[]
li=[]
for i in input_x:
if isinstance(i,list):
li.append(i)
else:
non_li.append(i)
for i in itertools.product(*li):
sub=non_li[:]
sub.extend(i)
print(sorted(sub))
output:
['1', '2', '3', '4', '5', '6']
['1', '2', '3', '4', '5', '6x']
['1', '2', '3', '4', '5x', '6']
['1', '2', '3', '4', '5x', '6x']
['1', '2x', '3', '4', '5', '6']
['1', '2x', '3', '4', '5', '6x']
['1', '2x', '3', '4', '5x', '6']
['1', '2x', '3', '4', '5x', '6x']

Multiple sorting in Python

I have an array with these datas:
[['1', '7', '14'], ['1', '1', '3'], ['1', '12', '3'], ['2', '3', '1'], ['1', '4', '9']]
I like to sort it (multiple):
>>> sorted(datas,key=lambda x:(x[0], x[1]))
[['1', '1', '3'], ['1', '12', '3'], ['1', '4', '9'], ['1', '7', '14'], ['2', '3', '1']]
but after sorted as it seems the 12 < 4. It should be:
[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]
Any idea? I need not natural sorting.
There is not wrong with sorted behaviour. Your data are lists of string, so it's doable.
>>> data = ['1', '12', '3', '2']
>>> sorted(data)
['1', '12', '2', '3']
If you want to sort as integer, it must be converted.
>>> sorted(data)
['1', '12', '2', '3']
>>> data = [['1', '7', '14'], ['1', '1', '3'], ['1', '12', '3'], ['2', '3', '1'], ['1', '4', '9']]
>>> sorted(data, key=lambda x: map(int, x))
[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]
Convert x[1] to int(x[1]):
sorted(d,key=lambda x:(int(x[0]), int(x[1])))
Output:
[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]
You are comparing strings, not ints. Therefor the order you get is the lexicographical order.
If you convert to int first
sorted(data, key=lambda x:(int(x[0]), int(x[1])))
you will get the desired result
[['1', '1', '3'], ['1', '4', '9'], ['1', '7', '14'], ['1', '12', '3'], ['2', '3', '1']]
Currently your sort is working on tuples string values. String values are determined similarly to any other iterable. When it compares two strings, it goes character by character from left-to-right or index 0 to index n-1 where n is the length of the iterable, until it finds one character that is larger than another. so when comparing '12' and '4', it notices that '4' is greater than '1' so it finishes right there. This system of ordering is known as lexicographical order.
To see the "value" of a character (In Python, a character is just a string of length 1), just use the ord function:
>>> ord('1')
49
>>> ord('4')
52
And to validate that the string '12' is indeed less than '4' because ord('1') < ord('4'):
>>> '12' < '4'
True
If you want to sort by the integer values of the strings, you have to convert the strings to ints by using the built-in int constructor.
sorted(datas,key=lambda x: (int(x[0]), int(x[1]))
Or if you want to cleanly handle iterables of all sizes, simply use a tuple-generator for the key:
sorted(datas,key=lambda x: tuple(int(e) for e in x))

Categories