List comprehension: muti-dimension items for each loop - python

I have a function (test_func) and I want to create a list:
def test_func(i):
return [[i, i+1], [i**2, i**3]]
output=[test_func(i) for i in range(5)]
The results are as follows:
[[[0, 1], [0, 0]],
[[1, 2], [1, 1]],
[[2, 3], [4, 8]],
[[3, 4], [9, 27]],
[[4, 5], [16, 64]]]
How to get the following results:
[[0, 1], [0, 0], [1, 2], [1, 1], [2, 3], [4, 8], [3, 4], [9, 27], [4, 5], [16, 64]]
Sincerely thank you,

Try this:
output=[v for i in range(5) for v in test_func(i)]
This produces:
[[0, 1], [0, 0], [1, 2], [1, 1], [2, 3], [4, 8], [3, 4], [9, 27], [4, 5], [16, 64]]

The second argument for the sum function is what you sum across - so in this case providing [], the sum is performed across lists (extending them, basically). This operation corresponds to flattening the list.
def test_func(i):
return [[i, i+1], [i**2, i**3]]
output = sum([test_func(i) for i in range(5)], [])

Without a function you could use itertools.chain.from_iterable
from itertools import chain
list(chain.from_iterable((([i, i+1], [i**2, i**3]) for i in range(5))))
which gives:
[[0, 1],
[0, 0],
[1, 2],
[1, 1],
[2, 3],
[4, 8],
[3, 4],
[9, 27],
[4, 5],
[16, 64]]

flat_out = [item for sublist in output for item in sublist]
[[0, 1],
[0, 0],
[1, 2],
[1, 1],
[2, 3],
[4, 8],
[3, 4],
[9, 27],
[4, 5],
[16, 64]]
or
def test_func(i):
return [[i, i+1], [i**2, i**3]]
output= [k for i in range(5) for k in test_func(i) ]
output

Related

List all combinations of 3 equally sized partitions of a list

I have a vector containing 15 values and would like to find all the possible ways to partition the vector into 3 equally sized partitions. I know there is n!/(n-r)!r! combinations to take r values out of a list of n values with replacement & this is easily generated with itertools in Python.
Does there exist an easy solution to list all combinations in this case as well?
Mathematically there will be n!/((n/3!)^3)/3! solutions, for example if n=15 there will be 126126 combinations and if n=6 there will be 15 combinations.
As the task needs to remove duplicates, which is not supported by itertools, I would recommend package more_itertools:
import more_itertools
n = 6
assert n%3 == 0
[x for x in more_itertools.set_partitions(range(n), 3) if len(x[0]) == len(x[1]) == len(x[2])]
[[[0, 1], [2, 3], [4, 5]],
[[0, 1], [3, 4], [2, 5]],
[[0, 1], [2, 4], [3, 5]],
[[1, 2], [0, 3], [4, 5]],
[[0, 2], [1, 3], [4, 5]],
[[1, 2], [3, 4], [0, 5]],
[[0, 2], [3, 4], [1, 5]],
[[1, 2], [0, 4], [3, 5]],
[[0, 2], [1, 4], [3, 5]],
[[2, 3], [1, 4], [0, 5]],
[[2, 3], [0, 4], [1, 5]],
[[1, 3], [2, 4], [0, 5]],
[[0, 3], [2, 4], [1, 5]],
[[1, 3], [0, 4], [2, 5]],
[[0, 3], [1, 4], [2, 5]]]

python sort a 2d list without using lambda

So I have this list:
lst = [[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]
I want to sort it accordingly: in reverse order for the first index, and if 2 items have the same first index, then in normal order by the second index
So the output will be:
lst = [[7, 0], [7, 1], [6, 1], [5, 0], [5, 2], [4, 4]]
I can do this using lambda function:
lst = [[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]
lst.sort(key = lambda x : (-x[0], x[1]))
But if I dont want to use lambda, how would I do it? I have this template, but not sure how to proceed from here:
lst = [[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]
def compare(input):
# put code here
lst.sort(key = compare(#what and how do I pass as input))
Python's sort is "stable" so it will keep items with the same sort key in their original relative order. This means that you can perform two sorts, starting with the least significant order and obtain the result you are looking for:
lst = [[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]
from operator import itemgetter
lst.sort(key=itemgetter(1)) # ascending 2nd index
lst.sort(key=itemgetter(0),reverse=True) # descending 1st index (stable)
print(lst)
[[7, 0], [7, 1], [6, 1], [5, 0], [5, 2], [4, 4]]
If you need to use a custom comparison function, you will find a solution here.

How can I sort the lists in the list?

I'd like to know how to sort the lists in the list. However, I don't want to align by key. I'd like to change it according to the following method.
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
# solution...
I_want_arr = [[2, 3], [1, 5], [1, 4], [3, 5], [2, 4]]
i tried it
for i in arr:
i.sort()
but, it didn't work
using list comprehenstion:
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
sorted_output = [sorted(l) for l in arr]
using map():
sorted_output = list(map(sorted, arr))
#Gabip's solution includes this and a more time efficient one, check that out first!
How about
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
I_want_arr = [sorted(x) for x in arr]
This outputs
[[2, 3], [1, 5], [1, 4], [3, 5], [2, 4]]

How can I merge a chain of intersecting 2-D lists (list of of lists) into a single 2-D list of lists

I have had to edit this question for the third time and present the data as simply as possible. I suppose the last one seemed very complex to recognize the pattern. Here is what I have now which looks more like the first one, for which #Andrej provided a solution, but I was unable to adapt to my scenario. I suppose that would go down to his conditions for merging. The original data is 3-D and is given below.`
original = [
[[0,1],[2,3],[4,5]],
[[0,1],[4,5]],
[[2,3]],
[[6,7],[8,9],[10,11]],
[[8,9],[6,7]],
[[6,7],[10,11]],
[[16,17],[12,13],[14,15]],
[[12,13]],
[[14,15],[16,17],[18,19]]
[[12,13],[16,17],[20,21]]
]
`
From the given data, I want to obtain another 3-D merged data`
merged = [
[[0,1],[2,3],[4,5]],
[[6,7],[8,9],[10,11]],
[[12,13],[14,15],[16,17],[18,19],[20,21]]
]
. I need to loop over all the 2-D list and merge all 2-D lists with common 1-D inner lists, while removing any duplicate 1-D lists. More like finding 2-D lists that have intersecting lists, and then merging all such 2-D lists. From the given original data, the first 2-D list intersects with the second through the list [0,1],[4,5] while the third 2-D list intersects with the first via [2,3]. Together, all three 2-D lists form a connected chain via their intersecting 1-D lists. This chain should be merged into a union of all three 2-D lists i.e [[0,1],[2,3],[4,5]]. I have tried the sample code below:
import numpy as np
original = [
[[0, 1], [2, 3], [4, 5]],
[[0, 1], [4, 5]],
[[2, 3]],
[[6, 7], [8, 9], [10, 11]],
[[8, 9], [6, 7]],
[[6, 7], [10, 11]],
[[16, 17], [12, 13], [14, 15]],
[[12, 13]],
[[14, 15], [16, 17], [18, 19]],
[[12, 13], [16, 17], [20, 21]]
]
tmp = {}
for subl in original:
for a, b in subl:
tmp.setdefault(a, set()).add(b)
merged = []
for k, v in tmp.items():
out.append([[k, i] for i in v])
print(merged)
But this is not giving the expected merged data as given above but this: [[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]], [[1, 0], [1, 1], [1, 2]], [[2, 0], [2, 1], [2, 2], [2, 3], [2, 4]]]. Any help would be hugely appreciated, please.
Try:
original = [
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]],
[[0, 1], [0, 2], [0, 3], [0, 4], [0, 5]],
[[0, 2], [0, 3], [0, 5]],
[[1, 0], [1, 2], [1, 4]],
[[1, 2], [1, 3], [1, 4]],
[[1, 0], [1, 2], [1, 3], [1, 4]],
[[1, 0]],
[[1, 0], [1, 3]],
[[2, 0], [2, 1], [2, 2], [2, 3]],
[[2, 1], [2, 2], [2, 3], [2, 4]],
[[2, 2], [2, 3], [2, 4]],
[[2, 3], [2, 4]],
[[2, 4]],
]
tmp = {}
for subl in original:
for a, b in subl:
tmp.setdefault(a, set()).add(b)
out = []
for k, v in tmp.items():
out.append([[k, i] for i in v])
print(out)
Prints:
[
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5]],
[[1, 0], [1, 2], [1, 3], [1, 4]],
[[2, 0], [2, 1], [2, 2], [2, 3], [2, 4]],
]

How to flatten a list in python?

I have a program which outputs solutions, which are lists of numbers as such:
[[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
What I want this to be turned into is:
[[1,1,5],[1,2,4],[1,3,3],[1,4,2],[1,5,1],[2,1,4],[2,2,3],[2,3,2],[2,4,1],[3,1,3],[3,2,2],[3,3,1],[4,1,2],[4,2,1],[5,1,1]]
Basically, each term in the whole list is headed by a number, which forms the first item of all possible solutions with that number, and then the following lists indicate what is to be added.
This should work. It works with the example that you have atleast.
result = [[[i[0]] + j for j in i[1:][0] ] for i in arr][0]
items = [[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
flat_items = []
for item in items:
leading = item[0]
for i in item[1]:
flat_items.append([leading]+i)
print(flat_items)
Yet another solution that gives you an output as you needed:
def flatten(lst):
result = []
for i in lst:
for j in i[1]:
pair = j[:]
pair.insert(0, i[0])
result.append(pair)
return result
Introduce two functions: merge and flatten.
The second function is taken from here:
def flatten(lst):
return [item for sublist in lst for item in sublist]
The first function is defined as:
def merge(lst):
return [[lst[0]] + x for x in flatten(lst[1:])]
Then call them:
s = [[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
print flatten([merge(x) for x in s])
Output is:
[[1, 1, 5], [1, 2, 4], [1, 3, 3], [1, 4, 2], [1, 5, 1], [2, 1, 4], [2, 2, 3], [2, 3, 2], [2, 4, 1], [3, 1, 3], [3, 2, 2], [3, 3, 1], [4, 1, 2], [4, 2, 1], [5, 1, 1]]

Categories

Resources