Turning a list into nested lists in python - python

Possible Duplicate:
How can I turn a list into an array in python?
How can I turn a list such as:
data_list = [0,1,2,3,4,5,6,7,8]
into a list of lists such as:
new_list = [ [0,1,2] , [3,4,5] , [6,7,8] ]
ie I want to group ordered elements in a list and keep them in an ordered list. How can I do this?
Thanks

This groups each 3 elements in the order they appear:
new_list = [data_list[i:i+3] for i in range(0, len(data_list), 3)]
Give us a better example if it is not what you want.

This assumes that data_list has a length that is a multiple of three
i=0
new_list=[]
while i<len(data_list):
new_list.append(data_list[i:i+3])
i+=3

Something like:
map (lambda x: data_list[3*x:(x+1)*3], range (3))

Based on the answer from Fred Foo, if you're already using numpy, you may use reshape to get a 2d array without copying the data:
import numpy
new_list = numpy.array(data_list).reshape(-1, 3)

new_list = [data_list[x:x+3] for x in range(0, len(data_list) - 2, 3)]
List comprehensions for the win :)

The following function expands the original context to include any desired list of lists structure:
def gen_list_of_lists(original_list, new_structure):
assert len(original_list) == sum(new_structure), \
"The number of elements in the original list and desired structure don't match"
list_of_lists = [[original_list[i + sum(new_structure[:j])] for i in range(new_structure[j])] \
for j in range(len(new_structure))]
return list_of_lists
Using the above:
data_list = [0,1,2,3,4,5,6,7,8]
new_list = gen_list_of_lists(original_list=data_list, new_structure=[3,3,3])
# The original desired outcome of [[0,1,2], [3,4,5], [6,7,8]]
new_list = gen_list_of_lists(original_list=data_list, new_structure=[2,3,3,1])
# [[0, 1], [2, 3, 4], [5, 6, 7], [8]]

The below one is more optimized and quite straightforward.
data_list = [0,1,2,3,4,5,6,7,8]
result =[]
i=0
while i <(len(data_list)-2):
result.append(data_list[i:i+3])
i+=3
print(result)
**output**
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]

Here is a generalized solution
import math
data_list = [0,1,2,3,4,5,6,7,8]
batch_size=3
n_batches=math.ceil(len(data_list)/batch_size)
[data_list[x*batch_size:min(x*batch_size+batch_size,len(data_list))]
for x in range(n_batches)]
It works even if the last sublist is not the same size as the rest (<batch_size)

Do you have any sort of selection criteria from your original list?
Python does allow you to do this:
new_list = []
new_list.append(data_list[:3])
new_list.append(data_list[3:6])
new_list.append(data_list[6:])
print new_list
# Output: [ [0,1,2] , [3,4,5] , [6,7,8] ]

Related

How to split string based on position in string

Given the following text:
input_value= """12
23
54"""
I want to return lists with the first and second elements of each line:
[[1,2,5], [2,3,4]]
I am trying to achieve this using a one-liner but struggling to access the correct indexes of each line and then placing them into a separate list. The number of returned lists should be equal to the number of digits present on each line:
I've tried the following as a base but clearly requires more logic in order to retrieve the correct digits:
new_list = [[elem] for elem in input_value.split('\n')]
Use a nested list comprehension:
out = [[int(i) for i in x] for x in zip(*input_value.split('\n'))]
Output:
[[1, 2, 5], [2, 3, 4]]
input_value= """12
23
54
"""
lst1 = []
lst2 = []
for i in input_value.splitlines():
if i:
lst1.append(int(i[0]))
lst2.append(int(i[1]))
lst = [lst1, lst2]
print(lst)
See if this works.
You could use something like
[[*elems] for elems in zip(*input_value.split("\n"))]
EDIT:
To create a list of integers, use
[[*map(int, elems)] for elems in zip(*input_value.split("\n"))]
Another possible solution:
[[list(map(int,x))[y] for x in input_value.split()] for y in range(2)]
Output:
[[1, 2, 5], [2, 3, 4]]

Add two lists which return a list the addition of the adjacent element

I want to write a function add_list, which adds two lists adjacent elements.
E.g. l1 = [1, 2, 3], l2= [1,2,3] should give [2,4,6]. I am lost and not sure how to approach it using loops. Can someone help please?
You can iterate both the lists using zip and then use list comprehension on them
[x+y for x,y in zip(l1, l2)]
Sample run:
>>l1 = [1, 2, 3]
>>l2= [1,2,3]
>>[x+y for x,y in zip(l1, l2)]
[2, 4, 6]
Other possible solution is to iterate through the index (can be used in list comprehension as well)
result = []
for i in range(len(l1)):
result.append(l1[i] + l2[i])
Output:
>>result
[2, 4, 6]
The following code will add numbers in two given list provided that both have same number of elements
def add_list(a, b):
result = [] # empty list
# loop through all the elements of the list
for i in range(len(a)):
# insert addition into results
result.append(a[i] + b[i])
return result
l1 = [1, 2, 3]
l2 = [1, 2, 3]
print(add_list(l1, l2))

Iterate Python List of Lists and Remove Final Index of Each Sublist, No Imports

There are a few similar questions to this one but not exactly the same:
I want to dynamically decrease a given input array or list of lists. For example:
matrix = [[0,1,2], [3,4,5],[6,7,8]]
Starting at 0 I need to iterate through and remove the final index - the iterative. So the output I would like to store in a new list is:
#output
[0,1,2], ,[3,4], [6]]
[0,1,2], ,[3,4], [6]] ==> which then flattens to [0,1,2,3,4,6]
Here's what I'm currently going after:
def get_list(matrix, stop_index):
temp = []
for i in range(0, stop_index):
for m in matrix:
temp.append(matrix[0:stop_index])
outside_list.append(temp)
return outside_list
I believe I am seeing well my over reliance on packages and libraries, so I am really trying to do this without outside packages or imports
Thank you for any help! I don't forget to green check mark.
Using list comprehension
l = [[0,1,2], [3,4,5],[6,7,8]]
ll = [ x[:len(l)-l.index(x)] for x in l]
# [[0, 1, 2], [3, 4], [6]]
print([x for y in ll for x in y ])
# [0, 1, 2, 3, 4, 6]
Simpler syntax:
matrix = [[0,1,2], [3,4,5],[6,7,8]]
outside_list = list()
for i in range(len(matrix)):
# matrix[i] is used to access very sublist in the matrix,
#[:3-i] is to slice every sublist from the beginning to (3 - current position)
outside_list.append(matrix[i][:3-i])
print(outside_list)
Some useful refernces
List slicing https://stackoverflow.com/a/509295/8692977
List comprehension: https://stackoverflow.com/a/34835952/8692977

Remove list if it's contained in another list within the same nested list Python

I have a nested list:
regions = [[1,2,3],[3,4],[1,3,4],[1,2,3,5]]
I want to remove every list in this nested list which is contained in another one, i.e., [3,4] contained in [1,3,4] and [1,2,3] contained in [1,2,3,5], so the result is:
result = [[1,3,4],[1,2,3,5]]
So far I'm doing:
regions_remove = []
for i,reg_i in enumerate(regions):
for j,reg_j in enumerate(regions):
if j != i and list(set(reg_i)-set(reg_j)) == []:
regions_remove.append(reg_i)
regions = [list(item) for item in set(tuple(row) for row in regions) -
set(tuple(row) for row in regions_remove)]
And I've got: regions = [[1, 2, 3, 5], [1, 3, 4]] and this is a solution, but I'd like to know what's the most pythonic solution?
(sorry for not posting my entire code before, I'm a new to this...
Here is a solution with list comprehension and all() function :
nested_list = [[1,2,3],[3,4],[1,3,4],[1,2,3,5],[2,5]]
result = list(nested_list) #makes a copy of the initial list
for l1 in nested_list: #list in nested_list
rest = list(result) #makes a copy of the current result list
rest.remove(l1) #the list l1 will be compared to every other list (so except itself)
for l2 in rest: #list to compare
if all([elt in l2 for elt in l1]): result.remove(l1)
#if all the elements of l1 are in l2 (then all() gives True), it is removed
returns:
[[1, 3, 4], [1, 2, 3, 5]]
Further help
all() built-in function: https://docs.python.org/2/library/functions.html#all
copy a list: https://docs.python.org/2/library/functions.html#func-list
list comprehension: https://www.pythonforbeginners.com/basics/list-comprehensions-in-python
I'm definitely overlooking a simpler route, but this approach works
list comprehension
from itertools import product
l = [[1,2,3],[3,4],[1,3,4],[1,2,3,5]]
bad = [i for i in l for j in l if i != j if tuple(i) in product(j, repeat = len(i))]
final = [i for i in l if i not in bad]
Expanded explanation
from itertools import product
l = [[1,2,3],[3,4],[1,3,4],[1,2,3,5]]
bad = []
for i in l:
for j in l:
if i != j:
if tuple(i) in product(j, repeat = len(i)):
bad.append(i)
final = [i for i in l if i not in bad]
print(final)
[[1, 3, 4], [1, 2, 3, 5]]

Creating a loop of many lists

I have a list of data:
data_list = [[1,2,3], [4,5,6], [7,8,9], ...]
I am trying to assign each element to a separate list so that:
Bin1 = [1,2,3]
Bin2 = [4,5,6]
....
Bin100 = [..,..,..]
I'm not sure how to do this without doing the manual way of initializing lists 1 by 1. Tried searching for a function how to go about it but have not found anything.
Once I have the lists initialized, I'd need to append the data from data_list:
for i in range(0, len(data_list)):
bin1.append(data_list[i][1])
bin2.append(data_list[i][2])
.......
Again, a shortcut way of doing this would be so useful!
You could use a dictionary if you wanted to access the lists with a key like "Bin1":
data_list = [[1,2,3], [4,5,6], [7,8,9]]
d = {}
for i, v in enumerate(data_list, 1):
d['Bin{}'.format(i)] = v
print(d) # >>> {'Bin1': [1, 2, 3], 'Bin3': [7, 8, 9], 'Bin2': [4, 5, 6]}
print(d['Bin1']) # >>> [1, 2, 3]
Or using a dict comprehension:
d = {'Bin{}'.format(i): v for i,v in enumerate(data_list, 1)}
you can simply write below code
l = [ [i,i+1,i+2] for i in range(1,YOUR_MAX_LENGTH,3) ]
hope this helps
Use dictionary comprehension to make a dictionary of lists, note this makes copies:
data_list = [[1,2,3], [4,5,6], [7,8,9]]
# To make copies
separate_lists = {'bin'+str(i): sublist
for i,sublist in enumerate(data_list,1)}
print (separate_lists)
To make a dictionary without making copies, this should work:
# To remove sublists from data_list and put them in the dictionary
separate_lists_not_copied = {}
for i in range(1,len(data_list)+1):
separate_lists_not_copied['bin'+str(i)] = data_list.pop(0)
print (separate_lists_not_copied)
Both print:
{'bin3': [7, 8, 9], 'bin1': [1, 2, 3], 'bin2': [4, 5, 6]}
use locals() to create variable name on-the-fly and iterate over all your sublists.
For those who are not aware of this function:
Update and return a dictionary representing the current local symbol table.
Free variables are returned by locals() when it is called in function
blocks, but not in class blocks.
data_list = [[1,2,3], [4,5,6], [7,8,9]]
for i, sublist in enumerate(data_list, 1):
locals()['bin_{}'.format(i)] = sublist
print bin_1 # [1, 2, 3]
print bin_3 # [7,8,9]
NOTE: Don't use uppercase on variable name since it is use by convention on for python classes. so bin_1 is a better name than Bin1

Categories