Using python random.choice in combination with list.append() - python

Lately, I've had some problems with Python's random.choice function.
I would expect the example script I've added to print out a list that consists of 3 items. Each of those items should be a list that contains two integers and one string.
For example: [[1, 4, 'a'], [2, 1, 'b'], [3, 4, 'c']]
from random import choice
pair = [
[1, 2], [1, 3], [1, 4],
[2, 1], [2, 3], [2, 4],
[3, 1], [3, 2], [3, 4],
[4, 1], [4, 2], [4, 3]
]
list = [0, 0, 0]
list[0] = choice(pair)
list[0].append('a')
list[1] = choice(pair)
list[1].append('b')
list[2] = choice(pair)
list[2].append('c')
print(list)
Most of the times the script works as expected. Sometimes however, it prints out something like this:
[[3, 2, 'a', 'c'], [4, 3, 'b'], [3, 2, 'a', 'c']]
Two of the items in the list not only consist of one string too many, but they are identical for some reason.
First I believed this had something to do with the append function.
However when I removed the random.choice component like this:
list = [0, 0, 0]
list[0] = [1, 2]
list[0].append('a')
list[1] = [2, 3]
list[1].append('b')
list[2] = [3, 4]
list[2].append('c')
print(list)
It still worked without flaws.
Same for the random.choice function, which didn't cause any problems by itself:
from random import choice
pair = [
[1, 2], [1, 3], [1, 4],
[2, 1], [2, 3], [2, 4],
[3, 1], [3, 2], [3, 4],
[3, 1], [3, 2], [4, 3],
list = [0, 0, 0]
list[0] = choice(pair)
list[1] = choice(pair)
list[3] = choice(pair)
print(list)
Next I tested what would happen when the list contained only one item and list.append and random.choice were only executed once
from random import choice
pair = [
[1, 2], [1, 3], [1, 4],
[2, 1], [2, 3], [2, 4],
[3, 1], [3, 2], [3, 4],
[4, 1], [4, 2], [4, 3]
]
list = [0]
list[0] = choice(pair)
list.append('a')
print(list)
This script behaved like I'd expect as well. Apparently my problem only occurs when random.choice and list.append are used executed several times on different items in a list, however I don't know how to explain it. Could someone explain what's happening and how to solve it?

First I open the REPL prompt and run your first block of code
>>> from random import choice
>>>
>>> pair = [
... [1, 2], [1, 3], [1, 4],
... [2, 1], [2, 3], [2, 4],
... [3, 1], [3, 2], [3, 4],
... [4, 1], [4, 2], [4, 3]
... ]
>>>
>>> list = [0, 0, 0]
>>>
>>> list[0] = choice(pair)
>>> list[0].append('a')
>>> list[1] = choice(pair)
>>> list[1].append('b')
>>> list[2] = choice(pair)
>>> list[2].append('c')
>>>
>>> print(list)
[[4, 1, 'a'], [3, 4, 'b'], [1, 2, 'c']]
Looks ok, but what happens if you inspect pair
>>> pair
[[1, 2, 'c'], [1, 3], [1, 4], [2, 1], [2, 3], [2, 4], [3, 1], [3, 2], [3, 4, 'b'], [4, 1, 'a'], [4, 2], [4, 3]]
So by appending to the lists that choice(pair) returns, you have inadvertently modified pair.
This is because choice(pair) doesn't copy the sublist.
If you mean to make a copy of the sublist, use
list[0] = choice(pair)[:]
or
list[0] = choice(pair).copy()

Related

How to reorder a list composed of lists

I am trying to tranform
[[1, 2, 3], [1, 2]]
into
[[1, 2, 3], [3, 2, 1], [2, 3, 1], [1, 2], [2, 1]]
But instead of the correct output, I am getting this:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2], [1, 2]]
Here is my code
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append(listTemp)
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
In your for loop, you are adding the same list again and again, but instead, you should make a copy of the list in the iteration.
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append([x for x in listTemp])
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
Output:
[[1, 2, 3], [3, 1, 2], [2, 3, 1], [1, 2], [2, 1]]

How can I sort the lists in the list?

I'd like to know how to sort the lists in the list. However, I don't want to align by key. I'd like to change it according to the following method.
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
# solution...
I_want_arr = [[2, 3], [1, 5], [1, 4], [3, 5], [2, 4]]
i tried it
for i in arr:
i.sort()
but, it didn't work
using list comprehenstion:
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
sorted_output = [sorted(l) for l in arr]
using map():
sorted_output = list(map(sorted, arr))
#Gabip's solution includes this and a more time efficient one, check that out first!
How about
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
I_want_arr = [sorted(x) for x in arr]
This outputs
[[2, 3], [1, 5], [1, 4], [3, 5], [2, 4]]

Problem getting pairs in a 3D list using list comprehension

I'm working with list comprehension but I'm having a trouble working this out, so, I have a 3D list in which I'm trying to obtain pairs in the inner lists, I created a code, in which I can obtain pairs, but it's not exactly what I need, here is my code:
mylist = [[[3, 2, 4, 3], [3, 2, 1], [2, 1]], [[1, 2, 3], [3, 1], [2, 1]]]
res = [[x[idx: idx+2] for i in mylist for x in i for idx in range(0, len(x) - 1)]]
print(res)
#res = [[[3, 2], [2, 4], [4, 3], [3, 2], [2, 1], [2, 1], [1, 2], [2, 3], [3, 1], [2, 1]]]
As you can see, I do get a 3D list with the pairs, but, it's not separated, its just a plain 3D list, I was expecting this:
#Output
res = [[[3, 2], [2, 4], [4, 3], [3, 2], [2, 1], [2, 1]], [[1, 2], [2, 3], [3, 1], [2, 1]]]
# ^
# Here is the separation
I'm working on my list comprehension, but I can't see where is happening the problem, I believe there is something wrong with the bracket, but I been trying different combinations but nothing seems to work, so any help will be appreciated.
Also, maybe this is bit of a stretch, but there is some way I can eliminate some repeated inner list in the 3D list, I mean, using res to get:
newres = [[[3, 2], [2, 4], [4, 3], [2, 1]], [[1, 2], [2, 3], [3, 1], [2, 1]]]
#[3, 2], [2, 1] eliminated
If you can point me to the right direction that would be great, thank you so much!
[[x[idx: idx+2] for x in i for idx in range(0, len(x) - 1)] for i in mylist ]
Sorry that I am not good at writing nested loops in one line. But this will remove duplicates and creates a 3D list with pairs:
mylist = [[[3, 2, 4, 3], [3, 2, 1], [2, 1]], [[1, 2, 3], [3, 1], [2, 1]]]
res = []
for inner in mylist:
temp = []
for each in inner:
for e in zip(each, each[1:]):
if list(e) not in temp:
temp.append(list(e))
res.append(temp)
print(res) # [[[3, 2], [2, 4], [4, 3], [2, 1]], [[1, 2], [2, 3], [3, 1], [2, 1]]]

extract list pattern from list of list in python

I have a list of the form -
a_list = [[1, [2, 3, 4]], [2, [3, 4]], [3, [4]]]
I want to convert it to the form -
b_list = [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
Using the list comprehension, I have tried with below code
for lst in tup:
for lst1 in tup[1]:
tup2 = [lst[0],lst1]
and getting (which is wrong)-
tup2 = [3, [3, 4]]
Please help, Thanks in advance
Simple to do with a list comprehension:
a_list = [[1, [2, 3, 4]], [2, [3, 4]], [3, [4]]]
b_list = [[x,y] for [x,b] in a_list for y in b]
print(b_list)
result:
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
using [x,b] unpacks the items into x as number and b as your list. Loop through elements of b and build the couples, flat-style.
You could try something like this , no matter how many int are there :
for sub_list in b:
for items in sub_list:
if isinstance(items, list):
track = sub_list.index(items)
first = sub_list[:track]
second = sub_list[track:][0]
import itertools
print([list(k) for k in itertools.product(first, second)])
test case:
b = [[1, [2, 3, 4]], [2, [3, 4]], [3, [4]]]
output:
[[1, 2], [1, 3], [1, 4]]
[[2, 3], [2, 4]]
[[3, 4]]
test case 2:
b=[[1,2,[2, 3, 4]], [2,3,5,6 ,[3, 4]], [3, [4]]]
output:
[[1, 2], [1, 3], [1, 4], [2, 2], [2, 3], [2, 4]]
[[2, 3], [2, 4], [3, 3], [3, 4], [5, 3], [5, 4], [6, 3], [6, 4]]
[[3, 4]]

How to flatten a list in python?

I have a program which outputs solutions, which are lists of numbers as such:
[[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
What I want this to be turned into is:
[[1,1,5],[1,2,4],[1,3,3],[1,4,2],[1,5,1],[2,1,4],[2,2,3],[2,3,2],[2,4,1],[3,1,3],[3,2,2],[3,3,1],[4,1,2],[4,2,1],[5,1,1]]
Basically, each term in the whole list is headed by a number, which forms the first item of all possible solutions with that number, and then the following lists indicate what is to be added.
This should work. It works with the example that you have atleast.
result = [[[i[0]] + j for j in i[1:][0] ] for i in arr][0]
items = [[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
flat_items = []
for item in items:
leading = item[0]
for i in item[1]:
flat_items.append([leading]+i)
print(flat_items)
Yet another solution that gives you an output as you needed:
def flatten(lst):
result = []
for i in lst:
for j in i[1]:
pair = j[:]
pair.insert(0, i[0])
result.append(pair)
return result
Introduce two functions: merge and flatten.
The second function is taken from here:
def flatten(lst):
return [item for sublist in lst for item in sublist]
The first function is defined as:
def merge(lst):
return [[lst[0]] + x for x in flatten(lst[1:])]
Then call them:
s = [[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
print flatten([merge(x) for x in s])
Output is:
[[1, 1, 5], [1, 2, 4], [1, 3, 3], [1, 4, 2], [1, 5, 1], [2, 1, 4], [2, 2, 3], [2, 3, 2], [2, 4, 1], [3, 1, 3], [3, 2, 2], [3, 3, 1], [4, 1, 2], [4, 2, 1], [5, 1, 1]]

Categories

Resources