making list inside a list using python - python

So I have two lists:
shape = [1,2,4]
board = [0,0,1,0,0,0,1,1,1]
I want to assign the board index to the shape index using a for loop so that i can put any shape size. I want the output of the shape to be [0,0,1].
I have tried doing:
list1 = []
for x in shape:
list1.append(board[x])
But the output it gives me is [0,1,0].
I want the output to be [0,0,1], the first three index of the board.

You are currently using
list1 = []
for x in shape:
list1.append(board[x])
This code means to make list1 equal to [board[1], board[2], board[4]], since you start with the empty list and then append board[x] for each x in shape (and since list indices start at 0 in Python). You probably want something like
list1 = []
for i in xrange(len(shape)):
list1.append(board[i])
Now i ranges from 0 to 2, as desired.

So what you mean is that the numbers in shape make no difference? You just want the first len(shape) items in board regardless of the numbers in shape?
In that case:
board[0:len(shape)]

list indices are 0-based, the items of board at indices [1,2,4] are infact [0,1,0].
if you want to use 1-based indices you need to adjust them:
list1 = [board[i-1] for i in shape]

Related

Failed to add element to nested lists

Background (not the subject of the question):
I am trying to solve the problem of generating all paths of length 3 from a list of all paths of length two in a list (p2 in the code below).
To that end I want to store all pairs of indices (i,j) for which p2[i][1]==p2[j][0] and `p2[i][2]==p2[j][1] (a path of length 2 is defined by a sequence of 3 vertices)
Question:
I tried store the indices in 2D lists whose entries are initially empty list that are appended newly encountered indices, but what is generated is a 2D list whose entries are lists that contain all indices.
Can someone explain what is actually going on behind the curtains and how to correctly add the indices to the innermost lists?
# -*- coding: utf-8 -*-
"""
Created on Sun May 29 10:10:40 2022
#author: Manfred Weis
"""
# generare all unsorted 3-tuples
from itertools import permutations
n=4
p2 = list(permutations(range(n),3))
print('p2:')
print(p2)
print()
N = len(p2)
Rows = [[[]]*n]*n # create 3D list
Cols = [[[]]*n]*n # create 3D list
for i in range(N):
print(str(i)+': Rows['+str(p2[i][1])+']['+str(p2[i][2])+']')
print(str(i)+': Cols['+str(p2[i][0])+']['+str(p2[i][1])+']')
(Rows[p2[i][1]][p2[i][2]]).append(i) # add to the most nested list
(Cols[p2[i][0]][p2[i][1]]).append(i) # add to the most nested list
for i in range(n):
for j in range(n):
print(str(i)+','+str(j)+':')
print(str(Rows[i][j]))
print(str(Cols[i][j]))
print()
You are having a shallow copy problem when you initialize your Rows and Cols 3D lists. Instead of using multiplication, you need to initialize them like so:
for k in range(n):
Rows.append([])
Cols.append([])
for l in range(n):
Rows[k].append([])
Cols[k].append([])
The problem with doing multiplication in order to initialize the 3D list of lists is that all n lists inside are all pointing to the same list, so when you append to one of them, you append to all of them, since they are technically only shallow copies of each other. Therefore, when you print them at the end, all the lists have all the numbers added to them, since they all point to the same place in memory. By initializing the 3D list using the method above, you are creating separate lists in separate locations in memory and you are inserting each of them into your Rows and Cols 3D lists.
Check out what happens when you do the following:
x = [[]]*2
x[0].append(5)
Output:
[[5], [5]]
But if you do the following, you solve the problem:
x = [[],[]]
x[0].append(5)
Output:
[[5], []]
Here are some other people's explanations which are better than mine:
List of lists changes reflected across sublists unexpectedly
Edit:
Here is a better more pythonic way to initialize Rows and Cols:
Rows = [[ [] for j in range(n)] for i in range(n)]
Cols = [[ [] for j in range(n)] for i in range(n)]

Adjusting code to output a list of lists regardless of inputs

I'm trying to pose this question a little differently since I have not been able to come up with a solution.
I have a code that outputs a list of lists. The output is dynamic meaning it can change depending on user input.
here is the code i use to produce the list of lists given three arrays:
Arr1 = [9,7,3,1]
Arr2 = [[14,6],[13,2]]
Arr3 = [0,2]
Z = np.array([[Arr1[i]] if not np.sum(Arr3 == i) else Arr2[i] for i in np.arange(Arr1.size)], dtype=object)
Z = [[list([14, 6])], [list([7])], list[([13, 2])], list[([1])]]
The code replaces certain elements in a list with an array based on indices given in another array (arr 3).
When the condition i = Arr3 is not met (say Arr3 was empty) and it just reverts to the original array the output of this code gives:
Z = [[9][7][3][1]]
which is sometimes the case given the inputs to produce the list.
Now i need to use a for loop to iterate over each sub list. Say just Z[0] for an example. I need to pull the list from index zero and iterate over those elements (regardless of the size of Z[0]).
Here is my issue:
For description of the issue, case 1 will be the situation when the output looks like this:
Z = [[list([14, 6])], [list([7])], list[([13, 2])], list[([1])]]
and case 2 will be when the output looks like this:
Z = [[9][7][3][1]]
For case 1, Z[0] looks like this:
[list([14,6])]
When I attempt to iterate this over a function using a for loop (say for i in Z[0]:) i get the error (can only concatenate list (not "float") to list).
for case 2 the output looks like this:
Z = [[9][7][3][1]]
Z[0] = [9]
And with that the code to iterate over the list works. However I need to work for case 1 as well
IF I remove brackets from this line of code here:
Z = np.array([[Arr1[i]] if not np.sum(Arr3 == i) else Arr2[i] for i in np.arange(Arr1.size)], dtype=object)
remove brackets around [Arr1[i]]
--->
Z = np.array([Arr1[i] if not np.sum(Arr3 == i) else Arr2[i] for i in np.arange(Arr1.size)], dtype=object)
Then
Z = [list([14,6]),list([7]),list([13,2]),list([1])]
and
z[0] = [14,6]
and the code to iterate over the list works! But, then it does not work for case 2, because the output looks like
[9 7 3 1]
Z[0] = 9
and I get the error 'float' object is not iterable.
Does anyone know a fix to this? How i can get the output to look right regardless of the input?

Two pairs of consecutive values list python

If you have a list in python like this:
list1 = [(1,2), (3,1), (4,1), (1,2), (3,1)]
If you have list1 in python and you want to find if two pairs of
consecutive values in a list in python are equal like (1,2) and
(3,1) is repeated twice and you want to update a variable lets say
i to 2 based on this.
How would you do this in python?
Here is how I got it, looped through the original list and made mini lists of every each pair, then I checked to see if that pair occurs twice.
lst = [(1,2), (3,1), (4,1), (1,2), (3,1)]
#iterate through list and append each pair of values
tmp = []
for i in range(0, len(lst)-1):
tmp.append(lst[i] + lst[i+1])
#see if any of the pairs appear twice, if so add to new list and get the length of that list to be your count
output = [x for x in tmp if tmp.count(x) > 1]
i = len(output)
print(i)

Removing values >0 in data set

I have a data set which is a list of lists, looking like this:
[[-0.519418066, -0.680905835],
[0.895518429, -0.654813183],
[0.092350219, 0.135117023],
[-0.299403315, -0.568458405],....]
its shape is (9760,) and I am trying to remove all entries where the value of the first number in each entry is greater than 0, so in this example the 2nd and 3rd entries would be removed to leave
[[-0.519418066, -0.680905835],
[-0.299403315, -0.568458405],....]
So far I have written:
for x in range(9670):
for j in filterfinal[j][0]:
if filterfinal[j][0] > 0:
np.delete(filterfinal[j])
this returns: TypeError: list indices must be integers or slices, not list
Thanks in advance for any help on this problem!
You can use numpy's boolean indexing:
>>> x = np.random.randn(10).reshape((5,2))
array([[-0.46490993, 0.09064271],
[ 1.01982349, -0.46011639],
[-0.40474591, -1.91849573],
[-0.69098115, 0.19680831],
[ 2.00139248, -1.94348869]])
>>> x[x[:,0] > 0]
array([[ 1.01982349, -0.46011639],
[ 2.00139248, -1.94348869]])
Some explanation:
x[:,0] selects the first column of your array.
x > 0 will return an array of the same shape where each value is replaced by the result of the element-wise comparison (i.e., is the value > 0 or not?)
So, x[:,0] > 0 will give you an array of shape (n,1) with True or False values depending on the first value of your row.
You can then pass this array of booleans as an index to your original array, where it will return you an array of only the indexes that are True. By passing in a boolean array of shape (n,1), you select per row.
You are talking about "shape", so I assume that you are using numpy. Also, you are mentioning np in your example code, so you are able to apply element wise operations together with boolean indexing
array = np.array([[-0.519418066, -0.680905835],
[0.895518429, -0.654813183],
[0.092350219, 0.135117023],
[-0.299403315, -0.568458405]])
filtered = array[array[:, 0] < 0]
Use a list comprehension:
lol = [[-0.519418066, -0.680905835],[0.895518429, -0.654813183],[0.092350219, 0.135117023],[-0.299403315, -0.568458405]]
filtered_lol = [l for l in lol if l[0] <= 0]
You can use a list comprehension that unpacks the first item from each sub-list and retains only those with the first item <= 0 (assuming your list of lists is stored as variable l):
[l for a, _ in l if a <= 0]
You can go through this in a for loop and making a new list without the positives like so:
new_list = []
for item in old_list:
if item[0] < 0:
new_list.append(item)
But I'd prefer to instead use the in built filter function if you are comfortable with it and do something like:
def is_negative(number):
return number < 0
filtered_list = filter(is_negative, old_list)
This is similar to a list comprehension - or just using a for loop. However it returns a generator instead so you never have to hold two lists in memory making the code more efficient.

Indexing a list using the values in a tuple in python

I have a list of tuples:
indices = [ (0,1) , (1,2) , (5,9) , ...]
each tuple represent an index to be used with a list of lists representing a grid.
what I am doing to extract the actual values corresponding to the indices is:
for index in indices:
x = grid [index[0]] [index[1]] # get the value and move on
Is there any better way to achieve this ? maybe something more "pythonic :D "
Thanks
You could use a list comp
[grid[x][y] for x, y in indices]
Or if you still need to do stuff once you get the value:
for x,y in indices:
i = grid[x][y]
# do stuff with i

Categories