Mapping issue with multiple lists in Python - python

I have two lists J1 and A1. I have another list J2 with some elements from J1. I want to print corresponding values from A1 using A2. I present the current and expected output.
J1 = [1, 7, 9, 11]
A1 = [2.1,6.9,7.3,5.4]
J2 = [1, 9]
J2,A2=map(list, zip(*((a, b) for a, b in zip(J2,A1))))
print(A2)
The current output is
[2.1, 6.9]
The expected output is
[2.1, 7.3]

Another variation, closer to the original:
A2 = [a for a,j in zip(A1,J1) if j in J2]

Define a dict using the keys in J1 and the values in A, then use the values in J2 as keys to look up in the new dict. operator.itemgetter will be useful.
>>> from operator import itemgetter
>>> d = dict(zip(J1, A1))
>>> A2 = list(itemgetter(*J2)(d))
>>> A2
[2.1, 7.3]

J1 = [1, 7, 9, 11]
A1 = [2.1,6.9,7.3,5.4]
J2 = [1, 9]
A2 = [A1[J1.index(a)] for a in J2]
print(A2)

Related

Multiply two lists but multiply each number in the first list by all numbers in the second list in python

I have two lists I want to multiply each number in the first list by all numbers in the second list
[1,2]x[1,2,3]
I want my result to be like this [(1x1)+(1x2)+(1x3),(2x1)+(2x2)+(2x3)]
numpy
a = np.array([1,2])
b = np.array([1,2,3])
c = (a[:,None]*b).sum(1)
output: array([ 6, 12])
python
a = [1,2]
b = [1,2,3]
c = [sum(x*y for y in b) for x in a]
output: [6, 12]
old answer (product per element)
numpy
a = np.array([1,2])
b = np.array([1,2,3])
c = (a[:,None]*b).ravel()
output: array([1, 2, 3, 2, 4, 6])
python
a = [1,2]
b = [1,2,3]
c = [x*y for x in a for y in b]
## OR
from itertools import product
c = [x*y for x,y in product(a,b)]
output: [1, 2, 3, 2, 4, 6]
def multiplyLists(list1: list, list2:list) -> list:
toReturn = []
for i in list1:
temp_sum = 0
for j in list2:
temp_sum += i * j
toReturn.append(temp_sum)
return toReturn
Another way using numpy (that you can extend to many other functions between two lists):
a = [1,2]
b = [1,2,3]
np.multiply.outer(a,b).ravel()
#array([1, 2, 3, 2, 4, 6])
As the comments point out a pure Python solution will be very different to a numpy solution.
Pyhton
Here it woud be straightforward to use a nested loop or list comprehension:
list1 = [1, 2]
list2 = [1, 2, 3]
lst_output = []
for i in list1:
for j in list2:
lst_output .append(i*j)
#equivalent alternative
lst_output = [i*j for i in list1 for j in list2]
Numpy
There are mny ways to go about it with numpy as well. Here's one example:
arr1 = np.array([1, 2])
arr2 = np.array([1, 2, 3])
xx, yy = np.meshgrid(arr1, arr2)
arr_output = xx * yy
# optionally (to get a 1d array)
arr_output_flat = arr_output.flatten()
Edit: Reading your question again I noticed you state you actually want the output to be 2 sums (of 3 products). I suggest you phrase more precisely what you want an what you've tried. But to provide that here's what you can do with the lists or arrays from above:
# Pure Python
lst_output = [sum(i*j for j in list2) for i in list1]
# Numpy
xx, yy = np.meshgrid(arr1, arr2)
arr_output = np.sum(xx * yy, axis=0)

Getting unique values in python using List Comprehension technique

I want to get the values that appear in one of the lists but not in the others. I even tried using '<>', it says invalid syntax. I am trying using list comprehensions.
com_list = []
a1 = [1,2,3,4,5]
b1 = [6,4,2,1]
come_list = [a for a in a1 for b in b1 if a != b ]
Output:
[1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
My expected output would be `[3, 5, 6]
What you want is called symmetric difference, you can do:
a1 = [1,2,3,4,5]
b1 = [6,4,2,1]
set(a1).symmetric_difference(b1)
# {3, 5, 6}
which you can also write as:
set(a1) ^ set(b1)
If you really want a list in the end, just convert it:
list(set(a1) ^ set(b1))
# [3, 5, 6]
a1 = [1,2,3,4,5]
b1 = [6,4,2,1]
If you really want to do that using list comprehensions, well, here it is, but it's really not the right thing to do here.
A totally inefficient version:
# Don't do that !
sym_diff = [x for x in a1+b1 if x in a1 and x not in b1 or x in b1 and x not in a1]
print(sym_diff)
# [3, 5, 6]
It would be a bit better using sets to test membership efficiently:
# Don't do that either
a1 = set([1,2,3,4,5])
b1 = set([6,4,2,1])
sym_diff = [x for x in a1|b1 if x in a1 and x not in b1 or x in b1 and x not in a1]
print(sym_diff)
# [3, 5, 6]
But if you start using sets, which is the right thing to do here, use them all the way properly and use symmetric_difference.
You can do
come_list =[i for i in list((set(a1) - set(b1))) + list((set(b1) - set(a1)))]
print(come_list)
Output
[3, 5, 6]
This new list contains all unique numbers for both of the lists together.
the problem with this line come_list = [a for a in a1 for b in b1 if a != b ] is that the items iterating over each item in the first list over all the items in the second list to check if it's inited but it's not giving unique numbers between both.

Multidimensional list match in python

This has caused some serious headache today.
Suppose I have two instances of my object, instance A and instance B. These come with properties is the form of a list. Say the two properties for A are
a1 = [1, 2, 3, 4, 5]
a2 = [10, 20, 30, 40, 50]
and those for B:
b1 = [5, 7, 3, 1]
b2 = [50, 20, 30, 20]
What I want is to simply find the indices in b1 and b2, where a pair equals the values in a1 and a2. So in this example this would be the indices 0 and 2 since for those we have
b1[0] = 5 and b2[0] = 50
which we find in a1 and a2 as the last entries. Same for index 2 for which we find (3, 30) in (b1, b2) which is also in (a1, a2).
Note here, that the lists a1 and a2 have always the same length as well as b1 and b2.
Any help? 😊
You can use a combination of zip, set and enumerate:
>>> a1 = [1, 2, 3, 4, 5]
>>> a2 = [10, 20, 30, 40, 50]
>>> b1 = [5, 7, 3, 1]
>>> b2 = [50, 20, 30, 20]
>>> a12 = set(zip(a1, a2))
>>> [i for i, e in enumerate(zip(b1, b2)) if e in a12]
[0, 2]
With zip, you group the pairs together, and with set you turn them into a set, as order does not matter and set have faster lookup. Then, enumerate gives you pairs of indices and elements, and using the list-comprehension you get those indices from b12 whose elements are in a12.
I think another structure would be better?
a tuple, or a key set ...
a = [(1,10),(2,20)] and so on
edit
well... tobias_k shows you how :)
Try this
In [38]: [b1.index(i[0]) for i in zip(a1,a2) for j in zip(b1,b2) if i==j]
Out[38]: [2, 0]
There is also the possibility to check for each element in (a1, a2) whether it is in (b1, b2) and it will return all matches in a list and will take care of duplicates:
a1 = [1, 2, 3, 4, 5]
a2 = [10, 20, 30, 40, 50]
b1 = [5, 7, 3, 1, 5]
b2 = [50, 20, 30, 20, 50]
# Construct list of tuples for easier matching
pair_a = [(i, k) for i, k in zip(a1, a2)]
pair_b = [(i, k) for i, k in zip(b1, b2)]
# Get matching indices (for each entry in pair_a get the indices in pair_b)
indices = [[i for i, j in enumerate(pair_b) if j == k] for k in pair_a]
gives
[[], [], [2], [], [0, 4]]

How do I shuffle a multidimensional list in Python

I know how to shuffle a simple List in Python by using the shuffle function from the random library shuffle(myList)
But how do I shuffle a multidimensional list?
myList[][]
shuffle(myList) didn't work.
You have to shuffle the top level list, then you can map the shuffle function to the sub lists like this in Python 2
from random import shuffle
foo = []
foo.append([1, 2, 3])
foo.append([4, 5, 6])
foo.append([7, 8, 9])
shuffle(foo)
map(shuffle, foo)
print foo
See python 2 fiddle
And like this in python 3
from random import shuffle
foo = []
foo.append([1, 2, 3])
foo.append([4, 5, 6])
foo.append([7, 8, 9])
shuffle(foo)
for ii, sublist in enumerate(foo):
shuffle(foo[ii])
print(foo)
see python 3 fiddle
Using only standard packages, the most efficient way I can think of is to unravel the array into a single list, shuffle, then reshape into a list of lists again.
import random
def shuffle2d(arr2d, rand=random):
"""Shuffes entries of 2-d array arr2d, preserving shape."""
reshape = []
data = []
iend = 0
for row in arr2d:
data.extend(row)
istart, iend = iend, iend+len(row)
reshape.append((istart, iend))
rand.shuffle(data)
return [data[istart:iend] for (istart,iend) in reshape]
def show(arr2d):
"""Shows rows of matrix (of strings) as space-separated rows."""
print ("\n".join(" ".join(row) for row in arr2d))
# Generate some ragged data (5 rows):
arr2d = []
for i,a in enumerate("ABCDE"):
n = random.randint(3,7)
arr2d.append([a+str(j) for j in range(1,n+1)])
# display original and shuffled data
print ("Original...")
show(arr2d)
print ("Shuffled...")
show(shuffle2d(arr2d))
print ("Again...")
show(shuffle2d(arr2d))
Sample output (Python 2.7):
Original...
A1 A2 A3
B1 B2 B3 B4 B5
C1 C2 C3
D1 D2 D3
E1 E2 E3 E4 E5
Shuffled...
A3 C1 E5
C3 D3 A2 E1 D1
A1 E2 C2
B5 B4 B2
B1 D2 E4 E3 B3
Again...
B2 C2 C3
B1 D2 E5 A3 D1
A1 E3 A2
B5 D3 C1
B4 E4 E1 B3 E2
The above works equally well on Python 3.4, by the way. The only version-dependent code features are print and range, and they are used agnostically.
I had this issue with trying to randomise questions and answers while maintaining the parring within the 2D list. At the time of writing this post, I have been learning python for only 3 weeks. My noob-solution was to create a random number, then use this number to pick from the list:
a_list = [["a4", 4], ["a3", 3],["a2", 2], ["a1", 1]]
a_pick = random.randint(0,3)
a_score = (a_list[a_pick])
This method allowed me to get a random selection from my list while keep the pairings I had written
First, import the numpy module:
import numpy as np
numpy has a method called called random.shuffle(). This method allwos you to shuffle a multi-dimensional list.
To shuffle a list using this method, you need to convert a list to a ndarray class, then pass it to random.shuffle().
>>> foo = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> foo = np.array(foo)
>>> foo
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
Now, shuffle it.
foo = np.random.shuffle(foo)
The value of foo will be something like this:
array([[1, 2, 3],
[7, 8, 9],
[4, 5, 6]])

using python 2.5 to subtract two lists

i have made a function which uses subtraction of two values stored in two lists as follows:
import sys,os
import math
c1 = [10]
c2 = [5]
d1 = [8]
d2 = [4]
x = d2 - c2
y = d1 - c1
z = x*x
w = y*y
answer = sqrt(z + w)
print answer
My error is: TypeError: unsupported operand type(s) for -: 'list' and 'list'
How can I get over the error that occurs due to subtraction not being possible between two lists, i.e., in lines d2-d1 and c2-c1? Is there a built-in function in the math module similar to sqrt that i might use to subtract lists?
Is this what you are trying to do?
import math
c = [10,5]
d = [8,4]
x = d[1] - c[1]
y = d[0] - c[0]
z = x*x
w = y*y
print math.sqrt(z+w)
You're using one element lists; If you want to perform that calculation specifically, just remove the braces. I'll assume that you actually do have multi-valued lists. A reasonable solution is to combine map(), which applies a function to each element in one or more lists, as well as some of the functions from the operator module, which turn many python operators (like + and -) into functions.
First well just set up some lists.
>>> import random
>>> d1 = [random.randrange(10) for ignored in range(10)]
>>> d2 = [random.randrange(10) for ignored in range(10)]
>>> c1 = [random.randrange(10) for ignored in range(10)]
>>> c2 = [random.randrange(10) for ignored in range(10)]
>>> c1
[1, 1, 7, 5, 5, 7, 4, 0, 7, 2]
>>> c2
[9, 2, 7, 7, 1, 1, 9, 3, 6, 8]
>>> d1
[0, 3, 4, 8, 9, 0, 7, 1, 6, 5]
>>> d2
[3, 9, 5, 2, 1, 9, 2, 7, 9, 5]
Next we just replace each of your operations into a map call to the corresponding operator.*
>>> import operator
>>> x = map(operator.sub, d2, c2)
>>> y = map(operator.sub, d2, c2)
>>> z = map(operator.mul, x, x)
>>> w = map(operator.mul, y, y)
>>> import math
>>> answer = map(math.sqrt, map(operator.add, z, w))
>>> print answer
[8.48528137423857, 9.899494936611665, 2.8284271247461903, 7.0710678118654755, 0.0, 11.313708498984761, 9.899494936611665, 5.656854249492381, 4.242640687119285, 4.242640687119285]
>>>
You can't subtract a whole list at once like that, even if there is only one item in the list. You have to do them one at a time. You could do it in a loop, or with a map. Here it is with a map:
import operator.sub
map(operator.sub, d2, c2)
map(operator.sub, d1, c1)

Categories