How to delete list inside nested list based on count? - python

import time
dc = []
def u():
for i in range(10):
if i < 5:
dc.append([i])
print(dc)
time.sleep(10)
while True:
u()
output after 1st run:[[0], [1], [2], [3], [4]]
output after 2nd run:[[0], [1], [2], [3], [4], [0], [1], [2], [3], [4]]
output for 3rd run:
[[0], [1], [2], [3], [4], [0], [1], [2], [3], [4], [0], [1], [2], [3], [4], [0], [1], [2], [3], [4]]
output for 4th run:
[[0], [1], [2], [3], [4], [0], [1], [2], [3], [4], [0], [1], [2], [3], [4], [0], [1], [2], [3], [4], [0], [1], [2], [3], [4]]
I want to delete the values from first iteration after 5 loops and keep the 2nd set of values until it reaches 5 loops.
How can I do this?

One way would be tracking the length of each list inserted, and then removing that number. Also your data makes no sense, since each item is also in it's own list, which is nonsensical.
x = [0], [1], [2], [3], [4]
y = [0], [1], [2], [3], [4]
dc = []
itemLengths = []
dc.extend(x)
itemLengths.append(len(x))
dc.extend(y)
itemLengths.append(len(y))
print(dc)
print(dc[itemLengths.pop(0):])
or a better way to handle this:
class U:
def __init__(self):
self.dc = []
self.insertLength = []
def add(self, data):
self.dc.extend(data)
self.insertLength.append(len(data))
self.remove()
return self
def remove(self):
if len(self.insertLength) == 6:
self.dc = self.dc[self.insertLength.pop(0):]
return self
def wait(self, timer):
time.sleep(10)
u = U()
u.add(x)
u.add(y)
u.add(x)
u.add(x)
u.add(x)
u.add(x)
print(u.insertLength)
print(len(u.insertLength))
print(u.dc)

Related

Is there a way to shorten this insetion sort

I have two lists I want to merge into one like so:
list_0=[[5], [4], [4], [1], [0], [7], [8], [3], [0]]
list_1=[[0], [9], [6], [4], [5], [9], [5], [9], [3]]
mine_position=[[5], [0], [4], [9], [4], [6], [1], [4], [0], [5], [7], [9], [8], [5], [3], [9], [0], [3]]
The code I have for merging them is:
for i in row:
mine_position.append(i)
mine_position.insert(1, list_1[0])
mine_position.insert(3, list_1[1])
mine_position.insert(5, list_1[2])
mine_position.insert(7, list_1[3])
mine_position.insert(9, list_1[4])
mine_position.insert(11, list_1[5])
mine_position.insert(13, list_1[6])
mine_position.insert(15, list_1[7])
mine_position.insert(17, list_1[8])
I want to shorten it so that the second part can be cleaner, but I can't seem to find a method that works.
You can just zip them together. No loops needed.
list_0=[[5], [4], [4], [1], [0], [7], [8], [3], [0]]
list_1=[[0], [9], [6], [4], [5], [9], [5], [9], [3]]
mine_position = list(zip(list_0, list_1))
We can see that your merged list's elements at even indices consists of elements from list_0 and the odd indices consists of elements from list_1. The below code snippet can be used to generate the merged list.
Code Snippet:
# Original Lists
list_0=[[5], [4], [4], [1], [0], [7], [8], [3], [0]]
list_1=[[0], [9], [6], [4], [5], [9], [5], [9], [3]]
# Merged List
result = []
total_elements = len(list_0) + len(list_1)
# Indices of respective lists
list0_idx = list1_idx = 0
for i in range(total_elements):
if i % 2 == 0:
result.append(list_0[list0_idx])
list0_idx += 1
else:
result.append(list_1[list1_idx])
list1_idx += 1
print(result)
How about this?
list_0=[[5], [4], [4], [1], [0], [7], [8], [3], [0]]
list_1=[[0], [9], [6], [4], [5], [9], [5], [9], [3]]
merged_list = []
for i in range(0, len(list_0)):
merged_list.append(list_0[i])
merged_list.append(list_1[i])
print(merged_list)
It shows this.
[[5], [0], [4], [9], [4], [6], [1], [4], [0], [5], [7], [9], [8], [5], [3], [9], [0], [3]]
You can first create a new variable and assign it as list_0. We do this so that list_0 is not altered. Then use a loop and insert the element of list_1 every 2 elements.
list_0=[[5], [4], [4], [1], [0], [7], [8], [3], [0]]
list_1=[[0], [9], [6], [4], [5], [9], [5], [9], [3]]
merged_list = list_0
idx = 1
for j in list_1:
merged_list.insert(idx,j)
idx += 2
print(merged_list)
#Result: [[5], [0], [4], [9], [4], [6], [1], [4], [0], [5], [7], [9], [8], [5], [3], [9], [0], [3]]
NOTE the reason we increment it by 2, is because at the start of the iteration, a new element will be added into the merged_list.
Using list comprehension:
[item for t in [(list_0[i], list_1[i]) for i in range(len(list_0))] for item in t]

Making each element of a nested list a list

I have a nested list say:
lst = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
And I would like the output to be:
new_list = [[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
this is what i am thinking, but I it is outputting a flat, list of list.
new_lst = []
for i in lst:
i = list(i)
for el in i:
new_list.append([el])
print(new_lst)
I would like to maintain the length of each predefined list in lst
Try List comprehension
[[ [e] for e in l] for l in lst]
You could use list comprehension and append every element to another list.
lst = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
new = [[[numbers] for numbers in elements] for elements in lst]
The above example adjusts for your desired output.
[[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
You can use numpy's reshape np.reshape
>>> import numpy as np
>>> lst = np.array([[1,2,3,4], [2,3,4,5], [3,4,5,6]])
>>> lst
array([[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6]])
>>> lst.shape
(3, 4)
>>> lst.reshape(3,4,1)
array([[[1],
[2],
[3],
[4]],
[[2],
[3],
[4],
[5]],
[[3],
[4],
[5],
[6]]])
>>> lst.reshape(3,4,1).tolist()
[[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
Another version, using recursion (you can have more level of depths in your input):
lst = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
def split(i):
if isinstance(i, list):
return [split(v) for v in i]
else:
return [i]
print(split(lst))
Prints:
[[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
You could use helper function to have more flexibility later of how you divide the smaller lists. based on an answer from here.
def split_list(alist, wanted_parts=1):
length = len(alist)
return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts]
for i in range(wanted_parts) ]
lst = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
ret =[]
for mini_list in lst:
ret.append(split_list(mini_list, len(mini_list)))
I think you had the right idea using multiple for loops. This should work:
list = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
for i in range(0, 3):
for j in range(0, 4):
(list[i])[j] = [(list[i])[j]]

Converting Nested List into Tuple

How can I take a nested List and group it into a tuple of three without importing any module. Please show the expanded for loops so I can understand it better.
For example, I want this nested List. Note this will always multiples of
3 sub lists so there is not a index error.
Thankyou.
[[1], [2], [3], [4], [5], [6], [7], [8], [9]] # Given
[(1, 2, 3), (4, 5, 6), (7, 8, 9)] # Result Wanted
No need for indexes. You can use next() on an iterator even inside a for loop:
xss = [[1], [2], [3], [4], [5], [6], [7], [8], [9]]
it = iter(xss)
answer = []
for x, in it:
answer.append((x, next(it)[0], next(it)[0]))
You can slice with a step size of 3 and zip to make the triples, do a nested unpacking in the for loop, and rebuild the triples without the wrapping lists.
xss = [[1], [2], [3], [4], [5], [6], [7], [8], [9]]
it = zip(xss[::3], xss[1::3], xss[2::3])
answer = []
for [x], [y], [z] in it:
answer.append((x, y, z))
given = [[1], [2], [3], [4], [5], [6], [7], [8], [9]] # because this is a list within a list
output = []
for i in range(0, len(given),3): # step size 3 indicated
temp = (given[i][0], given[i+1][0], given[i+2][0]) # therefore you need the "[0]" behind each given[i]
output.append(temp)
print (output)

Python list range access as a ring buffer

I have a Python list and would like to build the ranged loop list. It looks like a ring buffer. So if I have a list:
[[0], [1], [2], [3]]
I would like to get:
[[0], [1], [2], [3]]
[[1], [2], [3], [4]]
[[2], [3], [4], [0]]
[[3], [4], [0], [1]]
[[4], [0], [1], [2]]
I could do it by myself. But is there any better or smarter ways in Python 3?
The code I have tried:
N = 5
d_list = [[_] for _ in range(N)]
for i in range(N):
b1 = i
e1 = i + N - 1
b2, e2 = 0, 0
if e1 >= N:
e2 = e1 - N
print(d_list[b1:e1] + d_list[b2:e2])
what about using a collections.deque and rotate ?
import collections
N = 5
d = collections.deque(range(N))
for _ in range(N):
print(d)
d.rotate(1)
result:
deque([0, 1, 2, 3, 4])
deque([4, 0, 1, 2, 3])
deque([3, 4, 0, 1, 2])
deque([2, 3, 4, 0, 1])
deque([1, 2, 3, 4, 0])
rotate just changes the start of the list, no data is copied/moved, so it's very fast.
note:
you can convert into list if needed
my example is using integers, not lists containing one sole integer. This can be easily adapted if necessary.
This Python function rotates anything slice-able as you desire:
def rotate(l, y=1):
if len(l) == 0:
return l
y = -y % len(l) # flip rotation direction
return l[y:] + l[:y]
>>> rotate([1,2,3,4,5],2)
[4, 5, 1, 2, 3]
>>> rotate([1,2,3,4,5],-22)
[3, 4, 5, 1, 2]
>>> rotate('abcdefg',3)
'efgabcd'
>>> for i in range(N):
... print(d_list)
... d_list=rotate(d_list)
...
[[0], [1], [2], [3], [4]]
[[4], [0], [1], [2], [3]]
[[3], [4], [0], [1], [2]]
[[2], [3], [4], [0], [1]]
[[1], [2], [3], [4], [0]]
Note that in Python 3, range is not sliceable. You first would need to create a list with list(range(...))
The sign convention is the same as deque.rotate

Transposing the list

I have the following list:
y = [[0], [0], [0], [0], [1], [1], [1], [1]]
I would like to transpose it and have it in the following form:
[[0]
[0]
[0]
[0]
[1]
[1]
[1]
[1]]
When I did numpy.transpose(y), I got the following:
[[0 0 0 0 1 1 1 1]]
Any ideas?
[[0], [0], [0], [0], [1], [1], [1], [1]]
is exactly the same as this form:
[[0]
[0]
[0]
[0]
[1]
[1]
[1]
[1]]
You had a matrix with 8 rows and 1 column. Transposition executed on the matrix converted it to a matrix with just 1 row and 8 columns, so the output was correct.
If y is a list of lists, it displays as a single line
In [1]: y = [[0], [0], [0], [0], [1], [1], [1], [1]]
In [2]: y
Out[2]: [[0], [0], [0], [0], [1], [1], [1], [1]]
In [3]: print(y)
[[0], [0], [0], [0], [1], [1], [1], [1]]
You could of course do a line by line print
In [4]: for i in y: print(i)
[0]
[0]
[0]
[0]
[1]
[1]
[1]
[1]
If I make an array from it, I get a 2d (n,1) array
In [5]: Y = np.array(y)
In [6]: Y
Out[6]:
array([[0],
[0],
[0],
[0],
[1],
[1],
[1],
[1]])
In [7]: print(Y)
[[0]
[0]
[0]
[0]
[1]
[1]
[1]
[1]]
The array display does show rows and columns. Note that array print does not include commas (but its repr does).
If I transpose it, I get a (1,n) array, which displays as 1 line
In [8]: Y.T
Out[8]: array([[0, 0, 0, 0, 1, 1, 1, 1]])
There 3 different things that you may be confusing - the list, its print or string representation, and an array constructed from the list (and its print).
There is a list version of 'transpose':
In [9]: list(zip(*y))
Out[9]: [(0, 0, 0, 0, 1, 1, 1, 1)]
A longer list of lists may display as you want (if it doesn't neatly fit one line):
In [20]: z=[[i] for i in range(15)]
In [21]: z
Out[21]:
[[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9],
[10],
[11],
[12],
[13],
[14]]
Except - that's an ipython pretty print action. In a plain python
shell
>>> [[i] for i in range(15)]
[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14]]
Which just emphasizes my point - there's a difference between a list and its print representation.
There is a pprint.pprint (pretty print) that behaves more like ipython, switching to row prints when the list gets too long.

Categories

Resources