How could I indexing python list of lists without concatenating? - python

Assume I have input like this:
bl = [[0,1,2,3,4,5], [6,7,8,9], [10,11,12,13]]
idx = [10, 6, 3, 4, 9, 2]
and I want the output to be like this:
out = [[3,4,2], [6,9], [10]]
The logic behind is like this:
first I can view the lb_cat as some concatenated version:
lb_cat = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
Then index from the concatenated list:
pick = lb_cat[idx] = [10, 6, 3, 4, 9, 2]
At last, assigned the picked elements back to each group to get output of
out = [[3,4,2], [6,9], [10]]
The difficulty is that I cannot use operations like concatenated, since my input is not standard python list and it does not support concatenation operations.
What I want to do is to pick from a list of objects with the indices from the 'concatenated' view, but I actually pick from each of the elements of the list lb.
How could I do that in an efficient python way?
===========
Edit:
I have implemented a slow version, like this:
import numpy as np
bl = [[0,1,2,3,4,5], [6,7,8,9], [10,11,12,13]]
idx = [10, 6, 3, 4, 9, 2]
milestones = np.cumsum(np.array([len(el) for el in bl])).tolist()
milestones = [0,] + milestones
res = [[] for _ in bl]
for ix in idx:
for i, m in enumerate(milestones):
if ix < m:
res[i-1].append(ix)
break
This works for me, but it is too slow. Do I have a method to make it faster?

I am not sure if I understood your problem correctly, but I hope this will serve as a sufficient answer.
x=0 //to count the total number of numbers with concatination
out = [] //to store final result
for i in bl:
temp = []
for j in i:
if x in idx: //to check if you want xth indexed element
temp.append(j)
x+=1
if len(temp)>0: //only append if has an index in idx, i am not sure if you want this
out.append(temp)
print(out) //to print final output

Related

create sub-list of order integers present in a list and store them in another nested list in python

I have an array list like this:
list = [1,2,3,4,9,1,12,9,8,7,8,9,10,12,16,1,2,3,4,5,6,7,8,9,10]
I want to create a sub-list from a list of ordered numbers (which are already in sequence in arr_list for e.g. 1,2,3,4 are already in order, similarly 7,8,9,10 and last 10 numbers)
Final output will look like this:
[[1,2,3,4],[7,8,9,10],[1,2,3,4,5,6,7,8,9,10]]
Tried comparing if the i'th element of first for loop is less than the j'th element of second for loop.
This is what i've tried:
sub_list=[]
for i in range(0,length_of_list):
for j in range(i+1,length_of_list):
if (arr_list[i] < arr_list[j]):
sub_list.append(arr_list[i])
else:
pass
New to python, any leads are much appreciated.
Try this...
res, temp = [], []
lst = [1,2,3,4,9,1,12,9,8,7,8,9,10,12,16,1,2,3,4,5,6,7,8,9,10]
for i in lst:
if (not temp) or (temp[-1] == i-1):
temp.append(i)
else:
res.append(temp)
temp = [i]
res.append(temp)
print([i for i in res if len(i)>1])
Outputs:
[[1, 2, 3, 4], [7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
tell me if its okay for you...

Loop to select specific numbers from a given list

My problem is that in python i have a list of 1000 numbers. I want to select first 20 and store in "A" (another list) and next 30 in "B"(another list), again next 20 in "A", next 30 in "B" untill the list ends. How to do that? Can anyone help please?
You could use two nested list comprehension for this:
nums = list(range(2000))
A = [x for i in range( 0, len(nums), 50) for x in nums[i:i+20]]
B = [x for i in range(20, len(nums), 50) for x in nums[i:i+30]]
That means (for A): Starting at index 0, 50, 100 etc., take the next 20 elements and add them to A. Analogous for B. You might also use itertools.islice for the nums[i:i+n] part to avoid creating a bunch of temporary sub-lists.
Of course, this assumes that A and B do not already exist. If they do, and you want to add elements to them, use a regular loop and extend (not tested):
for i in range(0, len(nums), 50):
A.extend(nums[i :i+20])
B.extend(nums[i+20:i+50])
You do not have to check the indices again within the loop; if i+20 is already bigger than the last index in the list, B will just get extended with the empty list in the last step.
I made a function that can do what you're asking
def split_list(lst, gap1, gap2):
tmp = lst.copy()
out1, out2 = [], []
while tmp:
out1.extend(tmp[:gap1])
tmp = tmp[gap1:]
out2.extend(tmp[:gap2])
tmp = tmp[gap2:]
return out1, out2
gap1 and gap2 are the length of each subset you want to store, so in your case gap1=20 and gap2=30.
Example
numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
A, B = split_list(numbers, 2, 3)
print(A)
print(B)
Let's first define the followings:
A = [] #empty list
B = [] #empty list
And let's call your first list (that includes 1000 numbers), as my_list.
Then, a simple solution can be as following:
counter = 0
c_a = 2
c_b = 3
while (counter < len(my_list)):
A = A + my_list[counter:counter+c_a]
B = B + my_list[counter+c_a : counter + c_a + c_b]
counter = counter + c_a + c_b
I suggest generating a 2D nested list, which contains sublists each having 20 elements in it. Here is a one line way of doing that with a list comprehension:
x = range(1, 1001)
output = [x[idx*20:(idx*20 + 20)] for idx in range(0, len(x) / 20)]
Here is a version which operates on a smaller set of data, for demonstration purposes:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
output = [x[idx*3:(idx*3 + 3)] for idx in range(0, len(x) / 3)]
print(output) # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

How to create a new list everytime you loop and repeat the loop after appending elements to it?

This is my list
lst = [1,2,3,4,4,5,6,7,8,8,9,9,10,1]
I want this output
[1][2,3][4,4,5][6,7][8,8,9][9][10,1]
If the number is even and the next number is odd loop should break, and the next odd or even number should be appended in another list.
if there is even number, the list shouldn't be broken until the next odd is found.
lis = [1,2,3,4,4,5,6,7,8,8,9,9,10,1]
tempList = []
result = []
for item in lis:
tempList.append(item)
if item % 2 == 1:
result.append(tempList)
tempList = []
print(result)
It is hard to formulate a solution using break here.
May I suggest that you rewrite your psuedo-algorithm a little more concisely first. Something like:
For every item in the input list, append it to an output list.
If the item is odd then remember the current output list, and start
a new one.
Then, implemented in Python it looks like:
input_list = [1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 1]
output_list = [[]]
for x in input_list:
output_list[-1].append(x)
if x % 2 != 0:
output_list.append([])

Loop from a specific point in a list of lists Python

I would like to append to a new list all elements of an existing list of lists after a specific point
m = [[1,2,3],[4,5,10],[6,2,1]]
specific point = m[0][2]
newlist = [3,4,5,10,6,2,1]
You can directly slice off the remainder of the first target list and then add on all subsequent elements, eg:
m = [[1,2,3],[4,5,10],[6,2,1]]
y, x = 0, 2
new_list = m[y][x:] + [v for el in m[y+1:] for v in el]
# [3, 4, 5, 10, 6, 2, 1]
Here's a couple of functional approaches for efficiently iterating over your data.
If sublists are evenly sized, and you know the index from where to begin extracting elements, use chain + islice:
from itertools import chain, islice
n = 3 # Sublist size.
i,j = 0,2
newlist = list(islice(chain.from_iterable(m), i*n + j, None))
If you don't know the size of your sublists in advance, you can use next to discard the first portion of your data.
V = chain.from_iterable(m)
next(v for v in V if v == m[i][j])
newlist = list(V)
newlist.insert(m[i][j], 0)
This assumes there is no identical value earlier in the sequence.
You can put a conditional in your iteration and only add based on that condition. Once you hit that specific index, make your condition true. Something like this:
m = [[1,2,3],[4,5,10],[6,2,1]]
specific_point = (0,2)
newlist = [3,4,5,10,6,2,1]
output = []
for i in range(len(m)):
for j in range(len(m[i])):
if (i,j) < specific_point:
continue
output.append(m[i][j])
output:
[3, 4, 5, 10, 6, 2, 1]
why not flatten the initial list and go from there
flat_list = [item for sublist in m for item in sublist]
would return [1,2,3,4,5,10,6,2,1] so now you're really on flat_list[2:]
Most of the answers only work for this specific shape of nested list, but it's also possible to create a solution that works with any shape of nested list.
def flatten_from(sequence, path=[]):
start = path.pop(0) if path else 0
for item in sequence[start:]:
if isinstance(item, (list, tuple)):
yield from flatten_from(item, path)
else:
yield item
With the example from the question
>>> list(flatten_from([[1, 2, 3], [4, 5, 10], [6, 2, 1]], [0, 2]))
[3, 4, 5, 10, 6, 2, 1]
It also works with any shape and level of nesting of the input data
m = [[1], [[2], [3, 4, 5, 6, 7]], 8, [9, [10, 11]]]
flatten_from(m, [])) # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
flatten_from(m, [2]) # 8, 9, 10, 11
flatten_from(m, [1, 1, 3]) # 6, 7, 8, 9, 10, 11
This is a bit of a bastard algorithm, though. On one hand, it uses nice functional programming concepts: recursion and yield.
On the other hand it relies on the side effect of mutating the path argument with list.pop, so it's not a pure function.
Below solution will work for your case where your array is restricted to list of list and the size of 'sublist' is consistent throughout i.e "3" in your case
m = [[1,2,3],[4,5,10],[6,2,1]] #input 2D array
a, b = 0, 2 #user input --> specific point a and b
flat_list_m = [item for firstlist in m for item in firstlist] #flat the 2D list
print (flat_list_m[len(m[0])*a+b:]) #print from specific position a and b, considering your sublist length is consistent throughout.
I hope this helps! :)

How to add column elements of a 2D list and return result in a list?

Write a function that takes a two-dimensional list (list of lists) of
numbers as argument and returns a list which includes the sum of each
column. Assume that the number of columns in each row is the same.
I know how to traverse a row in a multidimensional list but have been facing problem on how to traverse the column elements of a multidimensional list. I'm just a beginner with python. There's no logic I can come up with using for loop or any of the list manipulation methods. I haven't come across the advance topics of lambda or anything of that sort. Any help would be appreciated.
Transpose and sum each column:
In [1]: arr = [[1,2,3],
[4,5,6]]
In [2]: list(map(sum, zip(*arr)))
Out[2]: [5, 7, 9]
zip(*arr) gives you the columns:
In [3]: list(zip(*arr))
Out[3]: [(1, 4), (2, 5), (3, 6)]
Then mapping sum on each column gives you the sum for each.
If you prefer a list comp:
In [5]: [sum(col) for col in zip(*arr)]
Out[5]: [5, 7, 9]
def _sum_of_columns_sample_(sample_list):
cols = len(sample_list[0])
mylist = []
for c in range(cols):
column_sum = 0
for row in sample_list:
column_sum += row[c]
mylist.append(column_sum)
return mylist
That's not the most beautiful piece of code I've ever come up with, but it should do the trick. If you would use packages such as numpy, things get significantly easier.
a = [1,2,3]
b = [4,5,6]
res = []
for i in range(len(a)):
res.append(a[i] + b[i])
A 2 dimensional list can be expressed a list of lists. That is
>>> mylist = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
>>>len(mylist)
You can now create a sum using nested for loops. Note that this assumes that there are the same number of elements in each column.
mysum = [0, 0, 0, 0]
for i in range(len(mylist)):
for j in range(len(mylist[0])):
mysum[i] += mylist[i][j]
print mysum
If you want to make it more general (and allow for different sized columns) without having to create an explicit mysum list you can use the following code.
mysum = []
for i in range(len(mylist)):
total = 0
for j in range(len(mylist[i])):
total += mylist[i][j]
mysum.append(total)
print mysum

Categories