I'm trying to write a nested loop that calculates (x+y)^2 for every value of y where the outer loop should print (x+y)^2. Here is my code so far:
x = [2,4,6,8,10,12,14,16,18]
y = [10,8.25,7.5,7,6.5,7,7.5,8.25,10]
for i in range(0 , len(x)):
# nested
#for j in range(0, len(y)):
for j in range(0, len(y)):
print( (x[i] + y[j])**2)
My output keeps printing repeated values like so:
144
105.0625
90.25
81
72.25
81
90.25
105.0625
144
Maybe you could try this:
NB - it works by zipping through two lists (same size) and do the math. If the size is unequal, then you should try zip_longest with some other default number (for this shorter list).
outs = []
for a, b in zip(x, y):
outs.append(pow((a+b), 2))
Example 2: one list is longer -
x = [2,4,6,8,10,12,14,16,18, 20] # adding 20 as extra number
y = [10,8.25,7.5,7,6.5,7,7.5,8.25,10]
from itertools import zip_longest #(a, b, fillvalue=0)
outs = []
for a, b in zip_longest(x, y, fillvalue=0):
outs.append(pow((a+b), 2))
Without using any library:
print([((x[i] if i < len(x) else 0) + (y[i] if i < len(y) else 0))**2 for i in range(max(len(x), len(y)))])
OUTPUT
[144, 150.0625, 182.25, 225, 272.25, 361, 462.25, 588.0625, 784]
Related
Is there a pythonic way to select N consecutive elements from a list or numpy array.
So Suppose:
Choice = [1,2,3,4,5,6]
I would like to create a new list of length N by randomly selecting element X in Choice along with the N-1 consecutive elements following choice.
So if:
X = 4
N = 4
The resulting list would be:
Selection = [5,6,1,2]
I think something similar to the following would work.
S = []
for i in range(X,X+N):
S.append(Selection[i%6])
But I was wondering if there is a python or numpy function that can select the elements at once that was more efficient.
Use itertools, specifically islice and cycle.
start = random.randint(0, len(Choice) - 1)
list(islice(cycle(Choice), start, start + n))
cycle(Choice) is an infinite sequence that repeats your original list, so that the slice start:start + n will wrap if necessary.
You could use a list comprehension, using modulo operations on the index to keep it in range of the list:
Choice = [1,2,3,4,5,6]
X = 4
N = 4
L = len(Choice)
Selection = [Choice[i % L] for i in range(X, X+N)]
print(Selection)
Output
[5, 6, 1, 2]
Note that if N is less than or equal to len(Choice), you can greatly simplify the code:
Choice = [1,2,3,4,5,6]
X = 4
N = 4
L = len(Choice)
Selection = Choice[X:X+N] if X+N <= L else Choice[X:] + Choice[:X+N-L]
print(Selection)
Since you are asking for the most efficient way I created a little benchmark to test the solutions proposed in this thread.
I rewrote your current solution as:
def op(choice, x):
n = len(choice)
selection = []
for i in range(x, x + n):
selection.append(choice[i % n])
return selection
Where choice is the input list and x is the random index.
These are the results if choice contains 1_000_000 random numbers:
chepner: 0.10840400000000017 s
nick: 0.2066781999999998 s
op: 0.25887470000000024 s
fountainhead: 0.3679908000000003 s
Full code
import random
from itertools import cycle, islice
from time import perf_counter as pc
import numpy as np
def op(choice, x):
n = len(choice)
selection = []
for i in range(x, x + n):
selection.append(choice[i % n])
return selection
def nick(choice, x):
n = len(choice)
return [choice[i % n] for i in range(x, x + n)]
def fountainhead(choice, x):
n = len(choice)
return np.take(choice, range(x, x + n), mode='wrap')
def chepner(choice, x):
n = len(choice)
return list(islice(cycle(choice), x, x + n))
results = []
n = 1_000_000
choice = random.sample(range(n), n)
x = random.randint(0, n - 1)
# Correctness
assert op(choice, x) == nick(choice,x) == chepner(choice,x) == list(fountainhead(choice,x))
# Benchmark
for f in op, nick, chepner, fountainhead:
t0 = pc()
f(choice, x)
t1 = pc()
results.append((t1 - t0, f))
for t, f in sorted(results):
print(f'{f.__name__}: {t} s')
If using a numpy array as the source, we could of course use numpy "fancy indexing".
So, if ChoiceArray is the numpy array equivalent of the list Choice, and if L is len(Choice) or len(ChoiceArray):
Selection = ChoiceArray [np.arange(X, N+X) % L]
Here's a numpy approach:
import numpy as np
Selection = np.take(Choice, range(X,N+X), mode='wrap')
Works even if Choice is a Python list rather than a numpy array.
a = [1,2,3,4,5,6,7]
b = [56,59,62,65,67,69]
def sumOfTwo(a,b,v):
for i in range (len(a)):
val_needed = v - a[i]
for j in range (len(b)):
if b[j] == val_needed:
x = b[j]
y = a[i]
print(x,y)
sumOfTwo(a,b,v=70)
Output: 5 65
What if more pairs are possible from the given lists in the problem, how do I do that?
Help.
What are more ways to achieve this?
If you just want to print matched values, you just have to indent the print statement to be inside theif, as stated below. Also, you should use a more pythonic approach to for loops and also for variable assignments.
a = [1,2,3,4,5,6,7]
b = [56,59,62,65,67,69]
def sumOfTwo(a,b,v):
for i in a:
val_needed = v - i
for j in b:
if j == val_needed:
x, y = j, i
print(x,y)
sumOfTwo(a,b,v=70)
Using a list comprehension:
a = [1,2,3,4,5,6,7]
b = [56,59,62,65,67,69]
c = [(x, y)
for x in a
for y in b
if x + y == 70]
print(c)
This yields
[(1, 69), (3, 67), (5, 65)]
I need to change the list's value to 0 if the input is below 0, and change it to 255 if the input is above 255.
i.e. if the list is [265,45,-23], I need to change it to [255,45,0].
Tried to figure it out for hours, but gave up a bit (the initial input is a tuple). Here is my code so far, but I have no idea which logic I should use:
def rgb(r, g, b):
x = (r,g,b)
x = list(x)
for i in x:
if i<0:
x=0
if i>255:
x=255
print(x)
You could do this in a single line using a list comprehension:
def rgb(r,g,b): return [min(255,max(0,n)) for n in (r,g,b)]
Output:
rgb(265,45,-23)
[255, 45, 0]
You don't need the tuple. Try this:
def rgb(r, g, b):
x = [r,g,b]
for i in range(len(x)):
if x[i] < 0:
x[i] = 0
if x[i] > 255:
x[i] = 255
return x
# Output: [255, 45, 0]
When you assign to x you're replacing the whole variable with a new value, not just the current element of the iteration.
You can use enumerate() to get the list index and value together, and use the index in the assignment.
for i, val in enumerate(x):
if val < 0:
x[i] = 0
elif val > 255:
x[i] = 255
You can also use a list comprehension:
x = [min(255, max(0, val)) for val in x]
You can use list comprehension to go through r, g and b. And at the same time create a new list that tests the conditions.
def rgb(r, g, b):
return [0 if x < 0 else 255 if x > 255 else x for x in (r,g,b)]
You can call it like:
print(rgb(265,45,-23))
or like:
x = [265,45,-23]
print(rgb(*x))
You can use max(0, min(255, x)) for a list element x. Then for the whole list you can use a list comprehension:
x = [max(0, min(255, y)) for y in x]
Alternatively you can use the ternary operator:
x = [255 if y > 255 else (0 if y < 0 else y) for y in x]
Solution
def rgb(r, g, b):
rgb_tuple = (r,g,b)
rgb_list = list(rgb_tuple)
new_list = []
for color in rgb_list:
if color<0:
new_list.append(0)
elif color>255:
new_list.append(255)
else:
new_list.append(color)
print(new_list)
return new_list
rgb(266, 80, -9)
I will like to find similar values of j in v and return x. when the value in j is not equal to v, I will like the code the detect the 2 value in v that j values between. so if j falls between v1 and v2, I will like the code to return max(x1,x2)- ( ((j-v1)/(v2-v1))*(max(x1,x2)-min(x1,x2)))
v= [100,200,300,400,500,600,700,800,900,1000,1100]
x= [67,56,89,21,90,54,38,93,46,17,75]
j= [200,300,400,460,500,600,700,800,870,900,950]
for i in range(len(v)-1):
if v[i] > j and V[i+1] < j:
p = max(x[i],x[i+1])- ( ((j-v[i])/(v[i+1]-v[i]))*(max(x[i],x[i+1])-min(x[i],x[i+1])))
elif v[i] ==j:
b= x[i]
print(p,b)
"""
n = [x[i] for i, v_ele in enumerate(v) if v_ele in j]
p= [x[i] for i, v_ele in enumerate(v) if v_ele > j and v_ele
print(n)
"""
I will like my answers to return
[56,89,21,48.6,90,54,38,93,60.1,46,31.5]
We can do this using the following two helper functions. Note that I think there may be a slight error for the fourth element in your expected output in the question - I get that value as 62.4 while you have 48.6.
Code:
def get_v_indx(j_ele, v):
if j_ele in v:
return v.index(j_ele)
else:
for i, ele in enumerate(v):
if ele > j_ele:
return i-1+(j_ele-v[i-1])/(ele-v[i-1])
def get_x_ele(i, x):
try:
return x[i]
except TypeError:
return x[int(i)] + (x[int(i)+1]-x[int(i)])*(i-int(i))
Usage:
>>> [get_x_ele(get_v_indx(j_ele, v), x) for j_ele in j]
[56, 89, 21, 62.4, 90, 54, 38, 93, 60.1, 46, 31.5]
Well, there is a couple of problems with your code:
First, after your if statement, there is a colon missing and one of your "v"s is capitalized. Computers are unforgiving - no typo's! ;)
Then, in that same line, you try to compare an integer (v[i] and v[i+1]) with a complete list of integers (j). Instead you need to go through your j list and compare each element in that list. I introduced an index ij for going through j.
When you compare that j value to v, you got your >< signs mixed up. Since your v list is ordered from small to big, it is impossible to be smaller than element i and simultaneously bigger than element i+1. ;)
Lastly, I'm not sure why you would store your value in two different variables (p and b) instead of the same. I did just that and called it a and printed it in an example alongside the j value it comes from.
v= [100,200,300,400,500,600,700,800,900,1000,1100]
x= [67,56,89,21,90,54,38,93,46,17,75]
j= [200,300,400,460,500,600,700,800,870,900,950]
for ij in range(len(j)):
for i in range(len(v)-1):
if v[i] < j[ij] and v[i+1] > j[ij]:
a = max(x[i],x[i+1])- ( ((j[ij]-v[i])/(v[i+1]-v[i]))*(max(x[i],x[i+1])-min(x[i],x[i+1])))
elif v[i] == j[ij]:
a = x[i]
print(j[ij]," leads to ",a)
Output:
200 leads to 56
300 leads to 89
400 leads to 21
460 leads to 48.6
500 leads to 90
600 leads to 54
700 leads to 38
800 leads to 93
870 leads to 60.1
900 leads to 46
950 leads to 31.5
I am trying to generate 3-tuples (x,y,z) in python such that no two of x , y or z have the same value. Furthermore , the variables x , y and z can be defined over separate ranges (0,p) , (0,q) and (0,r). I would like to be able to generate n such tuples. One obvious way is to call random.random() for each variable and check every time whether x=y=z . Is there a more efficient way to do this ?
You can write a generator that yields desired elements, for example:
def product_no_repeats(*args):
for p in itertools.product(*args):
if len(set(p)) == len(p):
yield p
and apply reservoir sampling to it:
def reservoir(it, k):
ls = [next(it) for _ in range(k)]
for i, x in enumerate(it, k + 1):
j = random.randint(0, i)
if j < k:
ls[j] = x
return ls
xs = range(0, 3)
ys = range(0, 4)
zs = range(0, 5)
size = 4
print reservoir(product_no_repeats(xs, ys, zs), size)