Create a Python List with Multiple Elements per Iteration - python

def f1(x): return [(x+1)*2-1, (x+1)*2-1]
def f2(x): return [(x+1)*2, (x+1)*2]
[[f1(i), f2(i)] for i in np.arange(3)]
This is the code to generate a list of 3 list-pairs elements:
[[[1, 1], [2, 2]], [[3, 3], [4, 4]], [[5, 5], [6, 6]]]
However, I would like to obtain a list like below with one line of for loop.
[[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6]]
This is how it works with multi-lines:
n = []
for i in np.arange(3):
n += [f1(i), f2(i)]
It's like trying to compose 2 elements per time where I don't know how to achieve += for one line of code. How can I do that?

[x for i in np.arange(3) for x in [f1(i), f2(i)]]
Use a list comprehension with two for clauses.

I could do something like this:
[f1(i) for i in np.arange(3)] + [f2(i) for i in np.arange(3)]
But is there any better way?

Related

Mapping a list right in Python

I have a question on how to map correctly my list.
I have the following code:
class Bar():
def __init__(self, i, j):
self.i = i-1
self.j = j-1
For the following list:
bars = [Bar(1,2), Bar(2,3), Bar(3,4), Bar(4,5), Bar(5,1),Bar(1,4), Bar(2,4), Bar(4,6), Bar(6,5)]
But for my problem, I have an array like this:
elementsmat=[[1, 1, 2], [2, 2, 3], [3, 3, 4], [4, 4, 5], [5, 5, 1], [6, 1, 4], [7, 2, 4], [8, 4, 6], [9, 6, 5]]
I used the following code to obtain an array where I removed the first element of each list of the list and then transformed it into a list.
s= np.delete(elementsmat, 0, 1)
r = s.tolist()
Output: [[1, 2], [2, 3], [3, 4], [4, 5], [5, 1], [1, 4], [2, 4], [4, 6], [6, 5]]
So, how can I apply the Bar function to all the elements of my new array correctly? I did this but I got the following error.
bars = map(Bar,r)
__init__() missing 1 required positional argument: 'j'
I thought it could be because in the first one the list has () and in my list I have [], but I am not sure.
You can use itertools.starmap instead of map (after importing itertools). Your current way calls Bar([1, 2]). starmap unpacks the lists into arguments. A generator/list comprehension is also an option.
(Bar(*x) for x in r)
Now you see why it's called starmap.
You need to unpack the nested lists into the call to Bar():
l = list(map(lambda x: Bar(*x), r))
itertools.starmap does the same thing.
Or, you can use a list-comprehension:
l = [Bar(i, j) for i, j in r]
A built-in functional approach
lst = [[1, 2], [2, 3], [3, 4], [4, 5], [5, 1], [1, 4], [2, 4], [4, 6], [6, 5]]
map(Bar, *zip(*lst))

How can I modify my code in order to avoid duplicate entries in this generator function?

The problem is as follows: Write a function choose_gen(S, k) that produces a generator that yields all the k-element subsets of a set S (represented as a sorted list of values without duplicates) in some arbitrary order.
Here is what I have so far:
def choose_gen(l: object, k: object) -> object:
if k>len(l):
return None
elif k == len(l):
yield sorted(l)
return
for i in l:
aux = l[:]
aux.remove(i)
result = choose_gen(aux, k)
if result:
yield from result
It runs but does not avoid the duplicate subsets. Could somebody please help to solve this issue? Thanks in advance.
an example of an input would be:
print([s for s in choose_gen([1,3,5,7], 2)])
actual output: [[5, 7], [3, 7], [3, 5], [5, 7], [1, 7], [1, 5], [3, 7], [1, 7], [1, 3], [3, 5], [1, 5], [1, 3]]
expected output: [[5, 7], [3, 7], [3, 5], [1, 7], [1, 5], [1, 3]]
I am not sure. But
I think that in the 6th line you have to write something after return. You have left it empty.
Or try,
new_menu = [s for s in choose_gen([1,3,5,7], (2)]
final_new_menu = list(dict.fromkeys(new_menu))
print(final_new_menu)

How can i sum up all values with the same index in a dictionary which each key has a nested list as a value?

I have a dictionary, each key of dictionary has a list of list (nested list) as its value. What I want is imagine we have:
x = {1: [[1, 2], [3, 5]], 2: [[2, 1], [2, 6]], 3: [[1, 5], [5, 4]]}
My question is how can I access each element of the dictionary and concatenate those with same index: for example first list from all keys:
[1,2] from first keye +
[2,1] from second and
[1,5] from third one
How can I do this?
You can access your nested list easily when you're iterating through your dictionary and append it to a new list and the you apply the sum function.
Code:
x={1: [[1,2],[3,5]] , 2:[[2,1],[2,6]], 3:[[1,5],[5,4]]}
ans=[]
for key in x:
ans += x[key][0]
print(sum(ans))
Output:
12
Assuming you want a list of the first elements, you can do:
>>> x={1: [[1,2],[3,5]] , 2:[[2,1],[2,6]], 3:[[1,5],[5,4]]}
>>> y = [a[0] for a in x.values()]
>>> y
[[1, 2], [2, 1], [1, 5]]
If you want the second element, you can use a[1], etc.
The output you expect is not entirely clear (do you want to sum? concatenate?), but what seems clear is that you want to handle the values as matrices.
You can use numpy for that:
summing the values
import numpy as np
sum(map(np.array, x.values())).tolist()
output:
[[4, 8], [10, 15]] # [[1+2+1, 2+1+5], [3+2+5, 5+6+4]]
concatenating the matrices (horizontally)
import numpy as np
np.hstack(list(map(np.array, x.values()))).tolist()
output:
[[1, 2, 2, 1, 1, 5], [3, 5, 2, 6, 5, 4]]
As explained in How to iterate through two lists in parallel?, zip does exactly that: iterates over a few iterables at the same time and generates tuples of matching-index items from all iterables.
In your case, the iterables are the values of the dict. So just unpack the values to zip:
x = {1: [[1, 2], [3, 5]], 2: [[2, 1], [2, 6]], 3: [[1, 5], [5, 4]]}
for y in zip(*x.values()):
print(y)
Gives:
([1, 2], [2, 1], [1, 5])
([3, 5], [2, 6], [5, 4])

How do I take the same index of different lists and put it into seperate lists?

Consider lists
a=[1,2,5,4,3]
b=[2,4,8,3,4]
I want my final lists to be
c=[1,2] d=[2,4] e=[5,8] f=[4,3] g=[3,4]
you can use a for loop:
result = []
for t in zip(a, b):
result.append(list(t))
result
output:
[[1, 2], [2, 4], [5, 8], [4, 3], [3, 4]]
You can use zip.
my_new_lists = list(map(list, zip(a,b)))

finding a list in a list of list based on one element

I have a list of lists representing a connectivity graph in Python. This list look like a n*2 matrix
example = [[1, 2], [1, 5], [1, 8], [2, 1], [2, 9], [2,5] ]
what I want to do is to find the value of the first elements of the lists where the second element is equal to a user defined value. For instance :
input 1 returns [2] (because [2,1])
input 5 returns [1,2] (because [1,5] and [2,5])
input 7 returns []
in Matlab, I could use
output = example(example(:,1)==input, 2);
but I would like to do this in Python (in the most pythonic and efficient way)
You can use list comprehension as a filter, like this
>>> example = [[1, 2], [1, 5], [1, 8], [2, 1], [2, 9], [2,5]]
>>> n = 5
>>> [first for first, second in example if second == n]
[1, 2]
You can work with the Python functions map and filter very comfortable:
>>> example = [[1, 2], [1, 5], [1, 8], [2, 1], [2, 9], [2,5] ]
>>> n = 5
>>> map(lambda x: x[0], filter(lambda x: n in x, example))
[1,2]
With lambda you can define anonyme functions...
Syntax:
lambda arg0,arg1...: e
arg0,arg1... are your parameters of the fucntion, and e is the expression.
They use lambda functions mostly in functions like map, reduce, filter etc.
exemple = [[1, 2], [1, 5], [1, 8], [2, 1], [2, 9], [2,5] ]
foundElements = []
** input = [...] *** List of Inputs
for item in exemple:
if item[1] in input :
foundElements.append(item[0])

Categories