Handling values less than tolerance in a list in Python - python

I have two lists A and B. I am mapping the lists using map() and using a tol value. But I am getting an error. I also present the expected output.
import numpy as np
A=[[0,1]]
B=[np.array([9.16435586e-15])]
tol=1e-12
if len(A) == 0 or len(B) == 0:
CA = []
CB = []
else:
CB, CA = map(list, zip(*((a, b) for a, b in zip(B, A) if a[0] > tol)))
print(CA)
print(CB)
The error is
in <module>
CB, CA = map(list, zip(*((a, b) for a, b in zip(B, A) if a[0] > tol)))
ValueError: not enough values to unpack (expected 2, got 0)
The expected output is
[[0, 1]]
[]

Related

How to unpack values from a list stored inside another list

I have a list containing some elements, a lit and some other elements like so [a, b, [c, d, e], f, g] and I would like to get [a, b, c, d, e, f, g]. I tried using itertools which I'm not familiar with, but I was unsucessfull:
from itertools import chain
a = 1
b = 2
c = [3, 4, 5]
d = 6
e = 7
list(chain(a, b, c, d, e))
It throws a TypeError
Any help is appreciated!
you could convert from a list mixed of lists and ints to a list strictly of lists, and then apply itertools chain.
from itertools import chain
l1= [1,2,[3,4,5],6,7]
l2 = list(chain.from_iterable(i if isinstance(i, list) else [i] for i in l1))
Or check the type and then extend or append the new list;
l1= [1,2,[3,4,5],6,7]
l2 = []
for i in l1:
l2.extend(i) if isinstance(i, list) else l2.append(i)
If you want a function that takes an arbitrary number of arguments, you could use the below solution
First I convert all input arguments to lists arg if isinstance(arg, list) else [arg], and then I use a "trick" with the summation function to flatten the lists.
def unpacker(*args):
return sum([arg if isinstance(arg, list) else [arg] for arg in args], [])
Example
a = 1
b = 2
c = [3, 4, 5]
d = 6
e = 7
print(unpacker(a, b, c, d, e))
>>> [1, 2, 3, 4, 5, 6, 7]

Is there a way to detect squares drawn by characters in a two-dimensional array?

I have a project in Python where you have a 5x4 two-dimensional list with empty strings as elements. These "slots" are later filled in with either "A" or "B", depending on the user input. After all the elements are changed with A's or B's, I want to find out how many 2x2 squares that are made up only by A's and B's (if they form at all) after there are 20 inputs.
[If a formation like this occurs, it should count as two squares.]
I can't wrap my head around this. So any help would be appreciated.
(I can't use any kind of third party libraries. But any built-in Python library would be OK.)
A 2x2 square contains just a single value. Thus, if you form the set of those 4 elements, that set would have length 1. This is easy enough to implement:
def count_squares(mat):
m = len(mat) #number of rows
n = len(mat[0]) #number of columns
count = 0
for i in range(m-1):
for j in range(n-1):
if len(set([mat[i][j],mat[i][j+1],mat[i+1][j],mat[i+1][j+1]])) == 1:
count += 1
return count
mat = [['A','A','A','B','B'],
['A','A','B','A','A'],
['A','A','B','B','A'],
['B','A','A','B','A']]
print(count_squares(mat)) #prints 2
Here is your code:
import numpy
def main(l1, l2, A, B, input_list):
check = numpy.ones((l1, l2)) * A
pos = []
for j1 in range(len(input_list) - l1 + 1):
for j2 in range(len(input_list[0]) - l2 + 1):
if input_list[j1:j1+l1, j2:j2+l2].all() == check.all():
pos.append([j1, j2])
return pos
if __name__ == "__main__":
A = 1 # Value of A
B = 0 # Value of B
l1 = 2 # Horizontal size of A values searched
l2 = 2 # Vertical size of A values searched
input_list = numpy.array([ # User input
[A, A, A, B, B],
[A, A, B, A, B],
[A, A, B, B, A],
[B, A, A, B, A],
])
pos = main(l1, l2, A, B, input_list)
print(f"{input_list = }")
print(f"{pos = }")
Result:
input_list = array([[1, 1, 1, 0, 0],
[1, 1, 0, 1, 0],
[1, 1, 0, 0, 1],
[0, 1, 1, 0, 1]])
pos = [[0, 0], [1, 0]]
The output return the top left corner of square of 2x2 containing only 1 values. Here you just need the len of 'pos' to count how many square you have...

Boolean values list to integer in Python

I'm having trouble with this lambdas syntax.
I'm trying to translate a list of booleans to an integer value, but I'm getting an error, I don't understand why.
Here is the code:
from functools import reduce
binary = [True, True, False, True]
L = list(range(len(binary))) #Step 1
print(L) #[0, 1, 2, 3]
L = map(lambda a: 2**a, L) #Step 2
print(L) #[1, 2, 4, 8]
L = zip(binary, L) #Step 3
print(L) #[(True, 1),(True, 2),(False, 4),(True, 8)]
L = filter(lambda a, b: a, L) #Step 4
print(L) #[(True, 1),(True, 2),(True, 8)] not sure
L = map(lambda a, b: b, L) #Step 5
print(L) #?????
L = reduce(lambda a, b: a + b, L) #Final step
print(L) #11
Output:
Traceback (most recent call last):
File "C:/Users/axel_/PycharmProjects/Python_Subject_Exam/19_new_exam_binary_list_translation.py", line 27, in <module>
L = reduce(lambda a, b: a + b, L)
TypeError: <lambda>() missing 1 required positional argument: 'b'
[0, 1, 2, 3]
<map object at 0x00000267FAFE5388>
<zip object at 0x00000267FAFE50C8>
<filter object at 0x00000267FAFE5248>
<map object at 0x00000267FAFE4EC8>
Process finished with exit code 1
Could anyone help me to debug?
I think this will solve your problem. I will write some comments in the code to help you understand:
from functools import reduce
binary = [True, True, False, True]
L = list(range(len(binary))) #[0, 1, 2, 3]
L = map(lambda a: 2**a, L) #[1, 2, 4, 8]
L = zip(binary, L) #[(True, 1), (True, 2), (False, 4), (True, 8)]
L = filter(lambda x: x[0], L) #<--- an item from zip() is an ((unpacked)) tuple
L = map(lambda x: x[1], L)
L = reduce(lambda a, b: a + b, L)
print(L) #11
This is one of the challenges if you are new to using iterators.
The iterator is evaluated as each item is pulled off the iterator, this means that when you call reduce to combine the result all of the lambda expressions are evaluated at that time. In your example this is equivalent to the following expression:
L = list(range(len(binary)))
L = reduce(lambda a, b: a + b,
map(lambda a, b: b,
filter(lambda a, b: a,
zip(binary,
map(lambda a: 2**a, L)
)
)
)
)
print(L)
Confusing?
In your example the line L = filter(lambda a, b: a, L) #Step 4 has an error. A filter expression takes a callable expression that takes a single argument along with an iterable but because it is not evaluated to the end you receive a confusing error.
One approach (and a good one when debugging) is to wrap each step in a call to list to force the evaluation to occur on each line eg L = list(filter(lambda a, b: a, L)). This will make the location of the error more apparent.
Alternatively use a generator expression rather than filter/map eg:
# filter (return odd numbers between 1 and 10)
result_a = filter(lambda a: a % 2, range(1, 11))
result b = (a for a in range(1, 11) if a % 2)
# map (return powers of 2)
result_a = map(lambda a: 2**a, range(11))
result_b = (2**a for a in range(11))
All of the results are the same but generator expressions have another trick, you can use tuple unpacking allowing for:
result = (b for a, b in zip(binary, range(len(binary))) if a)
Further, Python has other builtins that can simplify the code even more.
Enumerate will return a counter plus each element from an iterable allowing the first 3 steps to be simplified to:
# 1 step 1, 2 and 3 can be simplified with enumerate
L = ((i**2, b) for i, b in enumerate(L))
Next sum can be used to replace reduce, sum adds together all numerical values in an iterable:
L = reduce(lambda a, b: a + b, L)
# is equivalent to
L = sum(L)
And putting it all together the entire sequence can be simplified to:
L = sum(2**i for i, b in enumerate(binary) if b)
Hope that helps.

Adding lists to a sequence [duplicate]

This question already has answers here:
How do I iterate through two lists in parallel?
(8 answers)
Apply function to each element of a list
(4 answers)
Closed 8 months ago.
I want to perform an element wise multiplication, to multiply two lists together by value in Python, like we can do it in Matlab.
This is how I would do it in Matlab.
a = [1,2,3,4]
b = [2,3,4,5]
a .* b = [2, 6, 12, 20]
A list comprehension would give 16 list entries, for every combination x * y of x from a and y from b. Unsure of how to map this.
If anyone is interested why, I have a dataset, and want to multiply it by Numpy.linspace(1.0, 0.5, num=len(dataset)) =).
Use a list comprehension mixed with zip():.
[a*b for a,b in zip(lista,listb)]
Since you're already using numpy, it makes sense to store your data in a numpy array rather than a list. Once you do this, you get things like element-wise products for free:
In [1]: import numpy as np
In [2]: a = np.array([1,2,3,4])
In [3]: b = np.array([2,3,4,5])
In [4]: a * b
Out[4]: array([ 2, 6, 12, 20])
Use np.multiply(a,b):
import numpy as np
a = [1,2,3,4]
b = [2,3,4,5]
np.multiply(a,b)
You can try multiplying each element in a loop. The short hand for doing that is
ab = [a[i]*b[i] for i in range(len(a))]
Yet another answer:
-1 ... requires import
+1 ... is very readable
import operator
a = [1,2,3,4]
b = [10,11,12,13]
list(map(operator.mul, a, b))
outputs [10, 22, 36, 52]
Edit
For Python3.6+ map does not automatically unpack values.
Use itertools.starmap
import itertools
import operator
itertools.starmap(operator.mul, zip(a, b)))
you can multiplication using lambda
foo=[1,2,3,4]
bar=[1,2,5,55]
l=map(lambda x,y:x*y,foo,bar)
Fairly intuitive way of doing this:
a = [1,2,3,4]
b = [2,3,4,5]
ab = [] #Create empty list
for i in range(0, len(a)):
ab.append(a[i]*b[i]) #Adds each element to the list
gahooa's answer is correct for the question as phrased in the heading, but if the lists are already numpy format or larger than ten it will be MUCH faster (3 orders of magnitude) as well as more readable, to do simple numpy multiplication as suggested by NPE. I get these timings:
0.0049ms -> N = 4, a = [i for i in range(N)], c = [a*b for a,b in zip(a, b)]
0.0075ms -> N = 4, a = [i for i in range(N)], c = a * b
0.0167ms -> N = 4, a = np.arange(N), c = [a*b for a,b in zip(a, b)]
0.0013ms -> N = 4, a = np.arange(N), c = a * b
0.0171ms -> N = 40, a = [i for i in range(N)], c = [a*b for a,b in zip(a, b)]
0.0095ms -> N = 40, a = [i for i in range(N)], c = a * b
0.1077ms -> N = 40, a = np.arange(N), c = [a*b for a,b in zip(a, b)]
0.0013ms -> N = 40, a = np.arange(N), c = a * b
0.1485ms -> N = 400, a = [i for i in range(N)], c = [a*b for a,b in zip(a, b)]
0.0397ms -> N = 400, a = [i for i in range(N)], c = a * b
1.0348ms -> N = 400, a = np.arange(N), c = [a*b for a,b in zip(a, b)]
0.0020ms -> N = 400, a = np.arange(N), c = a * b
i.e. from the following test program.
import timeit
init = ['''
import numpy as np
N = {}
a = {}
b = np.linspace(0.0, 0.5, len(a))
'''.format(i, j) for i in [4, 40, 400]
for j in ['[i for i in range(N)]', 'np.arange(N)']]
func = ['''c = [a*b for a,b in zip(a, b)]''',
'''c = a * b''']
for i in init:
for f in func:
lines = i.split('\n')
print('{:6.4f}ms -> {}, {}, {}'.format(
timeit.timeit(f, setup=i, number=1000), lines[2], lines[3], f))
For large lists, we can do it the iter-way:
product_iter_object = itertools.imap(operator.mul, [1,2,3,4], [2,3,4,5])
product_iter_object.next() gives each of the element in the output list.
The output would be the length of the shorter of the two input lists.
create an array of ones;
multiply each list times the array;
convert array to a list
import numpy as np
a = [1,2,3,4]
b = [2,3,4,5]
c = (np.ones(len(a))*a*b).tolist()
[2.0, 6.0, 12.0, 20.0]
Can use enumerate.
a = [1, 2, 3, 4]
b = [2, 3, 4, 5]
ab = [val * b[i] for i, val in enumerate(a)]
The map function can be very useful here.
Using map we can apply any function to each element of an iterable.
Python 3.x
>>> def my_mul(x,y):
... return x*y
...
>>> a = [1,2,3,4]
>>> b = [2,3,4,5]
>>>
>>> list(map(my_mul,a,b))
[2, 6, 12, 20]
>>>
Of course:
map(f, iterable)
is equivalent to
[f(x) for x in iterable]
So we can get our solution via:
>>> [my_mul(x,y) for x, y in zip(a,b)]
[2, 6, 12, 20]
>>>
In Python 2.x map() means: apply a function to each element of an iterable and construct a new list.
In Python 3.x, map construct iterators instead of lists.
Instead of my_mul we could use mul operator
Python 2.7
>>>from operator import mul # import mul operator
>>>a = [1,2,3,4]
>>>b = [2,3,4,5]
>>>map(mul,a,b)
[2, 6, 12, 20]
>>>
Python 3.5+
>>> from operator import mul
>>> a = [1,2,3,4]
>>> b = [2,3,4,5]
>>> [*map(mul,a,b)]
[2, 6, 12, 20]
>>>
Please note that since map() constructs an iterator we use * iterable unpacking operator to get a list.
The unpacking approach is a bit faster then the list constructor:
>>> list(map(mul,a,b))
[2, 6, 12, 20]
>>>
To maintain the list type, and do it in one line (after importing numpy as np, of course):
list(np.array([1,2,3,4]) * np.array([2,3,4,5]))
or
list(np.array(a) * np.array(b))
you can use this for lists of the same length
def lstsum(a, b):
c=0
pos = 0
for element in a:
c+= element*b[pos]
pos+=1
return c
import ast,sys
input_str = sys.stdin.read()
input_list = ast.literal_eval(input_str)
list_1 = input_list[0]
list_2 = input_list[1]
import numpy as np
array_1 = np.array(list_1)
array_2 = np.array(list_2)
array_3 = array_1*array_2
print(list(array_3))

to check a condition for all the items in two list in python

I need to check a condition for all the items in two 1-dimensional lists
For example:
L = [12,23,56,123,13,15]
B = [45,89,12,45,19,89]
For the above two lists, how do I need to check the condition if(L[i] > (float(B[i]*1.1))) where 'i' is the index's starting from index 0 to all the items in the lists (in this case index is 0 to 5).I also need to print the items of list1(L) which fails the condition?
If I understood you right, you can do this with generator expression and zip function
L = [12,23,56,123,13,15]
B = [45,89,12,45,19,89]
all(x[0] > (x[1]*1.1) for x in zip(L, B))
or, as Ashwini Chaudhary suggested in comments, with values unpacking:
L = [12,23,56,123,13,15]
B = [45,89,12,45,19,89]
all(l > (b * 1.1) for l, b in zip(L, B))
To get items from list L which fails the condition:
[l for l, b in zip(L, B) if l <= (b * 1.1)]
not sure this is what you want but its a cool numpy thing
>>> L = numpy.array(L)
>>> B = numpy.array(B)
>>> B < L
array([False, False, True, True, False, False], dtype=bool)
>>> L[L > B* 1.1]
array([ 56, 123])
>>> all(L > B*1.1)
In order to print the ones who are matching, you could use
matching = (l > float(b * 1.1) for l, b in zip(L, B))
This gives you a generator which you can use as you want. E.g.:
for m, l in zip(matching, L):
if m:
print l
But you could as well directly generate an iterator of matching ones:
matching = (l for l, b in zip(L, B) if l > float(b * 1.1))
and then print them or just check for emptiness.
Depending on what you want to do, it might be appropriate to change the generator expression to a list comprehension:
matching = [l for l, b in zip(L, B) if l > float(b * 1.1)]

Categories

Resources