local maximum in lists within list - python

I have an optimization problem of trying to use less variety of products.
For example:
screws = [6,8,16,18,39]
I would like to exchange those 5 screws with 3. So I need to use the strongest so I could select, [8,18,39]. Using any other option will cause a waste—for example, screw 16 is too strong for location of 6, so [16,18,39] is not as good. I would like to write an algorithm that would be useful for a larger number of parts also. So far I tried this:
def split_list(data, n):
from itertools import combinations, chain
for splits in combinations(range(1, len(data)), n-1):
result = []
prev = None
for split in chain(splits, [None]):
result.append(data[prev:split])
prev = split
yield result
new_list = list(split_list(screws, 3))
#print list(split_list(screws, 3))
As a result of running this code I got a list of lists:
[[[6], [8], [16, 18, 39]],
[[6], [8, 16], [18, 39]],
[[6], [8, 16, 18], [39]],
[[6, 8], [16], [18, 39]],
[[6, 8], [16, 18], [39]],
[[6, 8, 16], [18], [39]]]
I would like to find out local maximums from all the list. For example in the first list [[6], [8],[16, 18, 39]], maximum = 6, maximum = 8, maximum = 39, and so on. But I don't know how to. Is there a way to find local maximum of all nested lists? I'm stuck in this moment, could you help me? I would appreciate also help with further progress.
Later on, I would like to check the sum of differences between maximum and other elements in the same list. So, 6-6 = 0, 8-8 = 0, and last 39-16+30-18-39-39 = 35. This will allow me to find out the smallest value from all lists of lists. This will be the most optimal solution. So the final result should be [[6, 8], [16, 18], [39]] and from it I would select [8,18,39].
This is basically my first program after tutorials and online classes, so all help is very welcome.

You have a list of lists of lists so just iterate over the list then get the max of each of the sublists inside the sublists.
l = [[[6], [8], [16, 18, 39]],
[[6], [8, 16], [18, 39]],
[[6], [8, 16, 18], [39]],
[[6, 8], [16], [18, 39]],
[[6, 8], [16, 18], [39]],
[[6, 8, 16], [18], [39]]]
for sub in l: # each sublist in l -> [[6], [8], [16, 18, 39]]etc..
print([max(ele) for ele in sub]) # each sublist inside each sublist -> [6], [8], [16, 18, 39]
[6, 8, 39]
[6, 16, 39]
[6, 18, 39]
[8, 16, 39]
[8, 18, 39]
[16, 18, 39]
So in your code just do the following:
for sub in split_list(screws, 3):
print([max(ele) for ele in sub])
To get the max minus each element you will have a lot of nested loops:
l = [[[6], [8], [16, 18, 39]],
[[6], [8, 16], [18, 39]],
[[6], [8, 16, 18], [39]],
[[6, 8], [16], [18, 39]],
[[6, 8], [16, 18], [39]],
[[6, 8, 16], [18], [39]]]
result = []
for sub in l:
for sub_ele in sub:
mx = max(sub_ele)
result.append([mx]+map(lambda x: mx-x,sub_ele))
[[6, 0], [8, 0], [39, 23, 21, 0], [6, 0], [16, 8, 0], [39, 21, 0], [6, 0], [18, 10, 2, 0], [39, 0], [8, 2, 0], [16, 0], [39, 21, 0], [8, 2, 0], [18, 2, 0], [39, 0], [16, 10, 8, 0], [18, 0], [39, 0]]

Related

Creating 2D list from 3D list in Python [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 11 months ago.
Assume I have a 3D list as following:
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 22, 23], [24, 25, 26]]]
I want to convert it to:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 22, 23], [24, 25, 26]]
I do not want to get lost inside of the for loops, is there a way this can be easily implemented?
Thanks in advance.
Try summing the list with []:
sum(your_3d_list, [])
Attempt it Online!
You can use numpy module and reshape function:
import numpy as np
myList = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 22, 23], [24, 25, 26]]]
array = np.array(myList)
array.reshape(9,3)
Output
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[19, 20, 21],
[22, 22, 23],
[24, 25, 26]])
You can use assert in order to make sure that this is the expected array:
expected = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 22, 23], [24, 25, 26]]
array = np.array(myList)
assert array.reshape(9,3).tolist() == expected
which works fine!
Note that, array.reshape(9,3) returns a numpy array and not a list. If you want to have the expected array as a list, you can use array.reshape(9,3).tolist()
array.reshape(9,3).tolist()
Output
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 22, 23], [24, 25, 26]]
Possible solution is the following:
lst = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 22, 23], [24, 25, 26]]]
result = [item for subitem in lst for item in subitem]
print(result)
Prints
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 22, 23], [24, 25, 26]]
​
You can use
import itertools
library, which is a standard python library.
use it like this:
import itertools
array = itertools.chain.from_iterable(array)
array = list(array)
the output will be:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 22, 23], [24, 25, 26]]
You can loop through each 2d list in the 3d list, then loop through each 1d list in the 2d list
_3d_list = [[[1, 2, 3], [3, 2, 1], [1, 3, 5]], [[4, 5, 6], [6, 5, 4], [4, 6, 8]]]
final_list = []
for _2d_list in _3d_list:
for _1d_list in _2d_list:
final_list.append(_1d_list)
print(final_list)
Output:
[[1, 2, 3], [3, 2, 1], [1, 3, 5], [4, 5, 6], [6, 5, 4], [4, 6, 8]]

Python put days from year in a list grouped by weeks

this is my actual code:
saptamani = []
for months in range(1, 12):
luna = calendar.monthcalendar(2020, months)
for i in luna:
prepare = [m for m in i if m > 0]
if [prepare[0] != prepare[-1]]:
new_w = [prepare[0], prepare[-1]]
saptamani.append(new_w)
Now my code print this:
[[1, 5], [6, 12], [13, 19], [20, 26], [27, 31], [1, 2], [3, 9], [10, 16], [17, 23], [24, 29], [1, 1], [2, 8], [9, 15], [16, 22], [23, 29], [30, 31], [1, 5], [6, 12], [13, 19], [20, 26], [27, 30], [1, 3], [4, 10],
[11, 17], [18, 24], [25, 31], [1, 7], [8, 14], [15, 21], [22, 28], [29, 30], [1, 5], [6, 12], [13, 19], [20, 26], [27, 31], [1, 2], [3, 9], [10, 16], [17, 23], [24, 30], [31, 31], [1, 6], [7, 13], [14, 20], [21, 2
7], [28, 30], [1, 4], [5, 11], [12, 18], [19, 25], [26, 31], [1, 1], [2, 8], [9, 15], [16, 22], [23, 29], [30, 30]]
What I wanted to do is to add the month number too, to be like this
[01.01, 05.01], [05.01, 12.01]....
You think something like this perhaps?
saptamani = []
for months in range(1, 12):
luna = calendar.monthcalendar(2020, months)
for i in luna:
prepare = [m for m in i if m > 0]
if [prepare[0] != prepare[-1]]:
new_w = ["{:02d}.{:02d}".format(prepare[0],months), "{:02d}.{:02d}".format(prepare[-1],months)]
saptamani.append(new_w)
This writes saptamani variable like this:
[['01.01', '05.01'], ['06.01', '12.01'], ['13.01', '19.01'], ['20.01', '26.01'], ['27.01', '31.01'], ['01.02', '02.02'], ['03.02', '09.02'], ['10.02', '16.02'], ['17.02', '23.02'], ['24.02', '29.02'], ['01.03', '01.03'], ['02.03', '08.03'], ['09.03', '15.03'], ['16.03', '22.03'], ['23.03', '29.03'], ['30.03', '31.03'], ['01.04', '05.04'], ['06.04', '12.04'], ['13.04', '19.04'], ['20.04', '26.04'], ['27.04', '30.04'], ['01.05', '03.05'], ['04.05', '10.05'], ['11.05', '17.05'], ['18.05', '24.05'], ['25.05', '31.05'], ['01.06', '07.06'], ['08.06', '14.06'], ['15.06', '21.06'], ['22.06', '28.06'], ['29.06', '30.06'], ['01.07', '05.07'], ['06.07', '12.07'], ['13.07', '19.07'], ['20.07', '26.07'], ['27.07', '31.07'], ['01.08', '02.08'], ['03.08', '09.08'], ['10.08', '16.08'], ['17.08', '23.08'], ['24.08', '30.08'], ['31.08', '31.08'], ['01.09', '06.09'], ['07.09', '13.09'], ['14.09', '20.09'], ['21.09', '27.09'], ['28.09', '30.09'], ['01.10', '04.10'], ['05.10', '11.10'], ['12.10', '18.10'], ['19.10', '25.10'], ['26.10', '31.10'], ['01.11', '01.11'], ['02.11', '08.11'], ['09.11', '15.11'], ['16.11', '22.11'], ['23.11', '29.11'], ['30.11', '30.11']]
Your script wrote integer values but for getting something like "01.01" you need string instead.

Slicing list of list in python, jumping one item [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 3 years ago.
I'm trying to reduce an important list of list in python as I don't need as much data to get where i want to go, ie drawing a route
mylist = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14],
[15, 16], [17, 18], [19, 20], [21, 22], [23, 24]]
I would like to "jump" some item of the list to reduce the size.
Example below where i skip 2 items every 3 lists.
mylist = [[1, 2], [7, 8], [13, 14], [19, 20]]
I tried with mylist[1::3] but wasn't successful
Thanks.
Your starting index was wrong - Python list indices start from 0. mylist[0::3], or equivalently mylist[::3], works just fine:
>>> mylist = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16], [17, 18], [19, 20], [21, 22], [23, 24]]
>>> mylist[::3]
[[1, 2], [7, 8], [13, 14], [19, 20]]
mylist[::3]
works for me.
mylist[1::3]
goes to the first element and skips to every third after that, giving:
[[3, 4], [9, 10], [15, 16], [21, 22]]

How to sum elements inside a nested list?

So, I have a list that looks something like this
[[[1, 2], [3, 4], [5, 6]],
[[7, 8], [9, 10], [11, 12]],
[[13, 14], [15, 16], [17, 18]],
[[19, 20], [21, 22], [23, 24]]]
And I want it to look like this
[[3, 7, 11],
[15, 19, 23],
[27, 31, 35],
[39, 43, 27]]
that is 3 = sum([1, 2]), 7 = sum([3, 4]), ....
I have tried nesting for loops but I haven't found anything that got the desired result, does anyone know how I could do this?
This will do the job quite nicely and imo is more readable than list comprehensions.
lists = [[[1, 2], [3, 4], [5, 6]],
[[7, 8], [9, 10], [11, 12]],
[[13, 14], [15, 16], [17, 18]],
[[19, 20], [21, 22], [23, 24]]]
new_lists = []
for nested in lists:
new_ls = []
for ls in nested:
new_ls.append(sum(ls))
new_lists.append(new_ls)
>>> new_lists
[[3, 7, 11], [15, 19, 23], [27, 31, 35], [39, 43, 47]]
You could also use list comprehensions:
[[sum(x) for x in triple] for triple in lists]
In the above list comprehension, triple will be your list of three doubles so the first for loop will be covering these. x will then be each list of doubles, inside of the triple so we are summing it, while keeping it inside the original triple by using this bracket around:
[sum(x) for x in triple]
output:
[[3, 7, 11], [15, 19, 23], [27, 31, 35], [39, 43, 47]]
If you are happy to use a 3rd party library, you can use NumPy and sum along a single dimension:
import numpy as np
A = np.array([[[1, 2], [3, 4], [5, 6]],
[[7, 8], [9, 10], [11, 12]],
[[13, 14], [15, 16], [17, 18]],
[[19, 20], [21, 22], [23, 24]]])
res = A.sum(2)
Result:
array([[ 3, 7, 11],
[15, 19, 23],
[27, 31, 35],
[39, 43, 47]])
See also: What are the advantages of NumPy over regular Python lists?

connected components using Breadth first search

I need to find the connected components of a graph.
I have a neighbour list of nodes:
neighbour_list = [[4], [2, 5], [1, 3, 8], [2, 14], [0, 9], [1], [10, 12], [13], [2, 14], [4, 10, 15], [6, 9], [17], [6], [7, 19, 20], [3, 8], [9, 21], [22], [11, 18], [17, 19], [13, 18, 26], [13, 26], [15, 27], [16, 23], [22, 24, 28], [23, 25, 29], [24], [19, 20, 30, 31], [21], [23, 29], [24, 28], [26, 31], [26, 30]]
For example node 0 has neighbour 4, node 1 has neighbours 2 and 5 etc...
What I want to find is a list of connected components. Say node 0 has neighbour 4, yet neighbour 4 also is a neighbour of node 9. Node 9 also has number 10 and 15 neighbours. So the list would be something like
[4,10,15....] etc including following neihbours.
the method I am trying to use is breadth first search.
I wrote the following algorithm:
def bfs(neighbour_list, node):
label_list =[]
for sub_neighbour_list in neighbour_list:
label_list.append(node)
queue = [node]
while queue:
u = queue[0]
for sub_neighbour in neighbour_list[u]:
if sub_neighbour not in queue:
label_list[sub_neighbour] = 0
queue.append(sub_neighbour)
queue.pop(0)
print(label_list)
return (label_list)
nothing happens when I run it. What is wrong?
thanks
What about:
neighbour_list = [[4], [2, 5], [1, 3, 8], [2, 14], [0, 9], [1], [10, 12], [13],
[2, 14], [4, 10, 15], [6, 9], [17], [6], [7, 19, 20], [3, 8],
[9, 21], [22], [11, 18], [17, 19], [13, 18, 26], [13, 26],
[15, 27], [16, 23], [22, 24, 28], [23, 25, 29], [24],
[19, 20, 30, 31], [21], [23, 29], [24, 28], [26, 31], [26, 30]]
def bfs(neighbour_list, root):
queue = []
seen = set()
queue.append(root)
seen.add(root)
while queue:
cn = queue.pop(0)
print("Current node: %d" % cn)
for nn in neighbour_list[cn]:
if nn not in seen:
queue.append(nn)
seen.add(nn)
print(" Found %d" % nn)
return seen
print bfs(neighbour_list, 0)
Which outputs:
Current node: 0
Found 4
Current node: 4
Found 9
Current node: 9
Found 10
Found 15
Current node: 10
Found 6
Current node: 15
Found 21
Current node: 6
Found 12
Current node: 21
Found 27
Current node: 12
Current node: 27
set([0, 4, 6, 9, 10, 12, 15, 21, 27])
Note that set isn't ordered. So the result of this function will return all nodes reachable by root, but not in any sort of order of when the algorithm reached it. If you want that, you could easily change seen to be a list.
This generator function will yield all connected components in a graph represented as an adjacency list. It also uses collections.deque for a queue instead of a list for efficient pops from the beginning of the queue.
from collections import deque
def connected_components(graph):
seen = set()
for root in range(len(graph)):
if root not in seen:
seen.add(root)
component = []
queue = deque([root])
while queue:
node = queue.popleft()
component.append(node)
for neighbor in graph[node]:
if neighbor not in seen:
seen.add(neighbor)
queue.append(neighbor)
yield component
Demo:
neighbour_list = [[4], [2, 5], [1, 3, 8], [2, 14], [0, 9], [1], [10, 12], [13],
[2, 14], [4, 10, 15], [6, 9], [17], [6], [7, 19, 20], [3, 8],
[9, 21], [22], [11, 18], [17, 19], [13, 18, 26], [13, 26],
[15, 27], [16, 23], [22, 24, 28], [23, 25, 29], [24],
[19, 20, 30, 31], [21], [23, 29], [24, 28], [26, 31], [26, 30]]
print(list(connected_components(neighbour_list)))
# [[0, 4, 9, 10, 15, 6, 21, 12, 27],
# [1, 2, 5, 3, 8, 14],
# [7, 13, 19, 20, 18, 26, 17, 30, 31, 11],
# [16, 22, 23, 24, 28, 25, 29]]

Categories

Resources