Get the integer in between two values - python

For some coordinate processing I need to be able to find the integers in between 2 values. I know you can use range() for this, but I need it to work even when you switch the 2 values around. range(x, y) won't give the same results as range(y, x). Is there a trick to do this?
EDIT: Torxed's comment was exactly what i needed: range(min(x, y), max(x, y))

There are 3 different options that have been suggested:
As proposed in #Torxed's comment:
range(min(x, y), max(x, y))
As proposed in #tobias_k's comment:
range(*sorted([x, y]))
Or mine, using a ternary condition:
range(x, y) if x < y else range(y, x)

Wasn't quite sure what's asked and just scribbled some weird code.
Both approaches can be useful depending on whether we want to keep the "discarding the 'b'" behaviour.
range(2,5)
#[2, 3, 4]
range(5,2,-1)
#[5, 4, 3]
range(5,2,2 * (5<2) - 1)
#[5, 4, 3]
##### Approach A
a = 5;b = 2
range(a, b, 2*(a<b) -1 )
#[5, 4, 3]
a = 2; b = 5
range(a, b, 2*(a<b) -1 )
#[2, 3, 4]
##### Approach B from #tobias_k
a = 5;b = 2
range(*sorted([a,b]))
#[2, 3, 4]
a = 2;b = 5
range(*sorted([a,b]))
#[2, 3, 4]

Related

Python equivalent to replace() in R

Is there a powerful replace function in Python, something equivalent to replace(x, l, y) in R?
e.g.
x = [0,0,0,0,0,0,0,0,0, 0]
l = [True,False,True,True,False,False,False,False,True, False]
y = [5, 6, 7, 8]
The number of values in y matches the number of True in l. In R,
replace(x, l, y) will have x replaced by y corresponding to the True positions in l.
Is there a similar function in Python I can call? If not, any suggestions how to make it working?
Thanks much in advance!
Since the number of Trues and the number of elements in y are the same, we can a generator over y, and then use a list comprehension to build the result. We extract from y if the corresponding element in l is True, else we extract from x:
iter_y = iter(y)
[next(iter_y) if l_item else x_item for l_item, x_item in zip(l, x)]
This outputs:
[5, 0, 6, 7, 0, 0, 0, 0, 8, 0]

Python Function Returning List Objects Out of Order

I'm relatively new to the Python language. I'm aware of most of the basic functionality & theory, all the different classes of object and their behavior/properties etc.
Anyway, I was writing basic functions to explore different concepts in practice and get to know the language more intuitively. One in particular has left me vexed! Can anyone share any insight into why this result is not as expected?
Here is the code I ran:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
for n in k:
k[k.index(n)] = n * 2
x, y, z = k
return k
test_func(test_list)
print(test_list)
print(x)
print(y)
print(z)
I would have expected the result to be:
[4, 8, 12]
4
8
12
However, the actual result is as follows:
[8, 4, 12]
8
4
12
It seems that the first two items of the list have been swapped.
I can't see what could be causing this? If anyone can see what's happening here, please share the insight!
Thanks,
Oscar South
After first iteration you list look like [4,4,6] so k.index(4) return 0 index and multiple it by 2. So final result is [8,4,12].
I think you meant to do this:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
for i in range(len(k)):
k[i] = k[i] * 2
x, y, z = k
return k
You're mixing indexes with values, and using index() to find the position in an array is incorrect, most of all because you're modifying the list and you'll find the same elements again but in different positions, better use a range to iterate over the indexes and retrieve the values.
Also, using globals is not cool. In fact, the whole procedure should be written like a list comprehension instead - simple and idiomatic:
[2 * x for x in test_list]
=> [4, 8, 12]
In the first iteration the first element is changed to 4. In the second iteration the index of 4 is 0 not 1 as you expect.
Try this:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
l = list()
for n in k:
print(n, k.index(n))
l.append(n * 2)
x, y, z = l
return l
test_func(test_list)
print(test_list)
print(x)
print(y)
print(z)
You can condense the code into a list comprehension and unpacking:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
x, y, z = [i*2 for i in k]
return [x, y, z]

Python Reduce Math Equation

I am given a list of numbers a = [1, 2, 3, 4, 5, 6] and using only Python's reduce function, return a value. The value is calculated by:
(((...(a[0] + a[1]) * a[2] + a[3]) * a[4] + ...)
So in the above example where a = [1, 2, 3, 4, 5, 6], the answer should be ((1 + 2) * 3 + 4) * 5 + 6 = 71
I'm fairly new to Python and I'm trying to learn it:
reduce(lambda x,y: x * y, map(lambda x,y: x+y, numbers))
The tricky bit is, of course, that you have to alternate between two functions in reduce. Since you can't really keep track of the current position in the list1), in order to decide which operation to use, your best chance is to use an iterator that alternates between + and *.
You could use itertools.cycle to alternate between add and mul and use those in reduce
>>> import itertools, operator
>>> op = itertools.cycle([operator.add, operator.mul])
>>> a = [1, 2, 3, 4, 5, 6]
>>> reduce(lambda x, y: next(op)(x, y), a)
71
If you can't use those modules, you can make a generator expression alternating between + and * using lambdas in a ternary expression. The rest remains the same.
>>> op = ((lambda x,y:x+y) if i % 2 == 0 else (lambda x,y:x*y) for i in range(len(a)))
>>> a = [1, 2, 3, 4, 5, 6]
>>> reduce(lambda x, y: next(op)(x, y), a)
71
1) Well, you can, using enumerate(a), or zip(range(len(a)), a), if you prefer...
>>> a = [1, 2, 3, 4, 5, 6]
>>> reduce(lambda x, y: (y[0], x[1]+y[1]) if x[0]%2==0 else (y[0], x[1]*y[1]), enumerate(a))[1]
71
Or shorter, using tuple-unpacking in the lambdas, but this only works in Python 2.x:
>>> reduce(lambda (i,x),(j,y): (j, x+y) if i%2==0 else (j, x*y), enumerate(a))[1]
Improving the solution of Akash Patel, i have come up with this, with only reduce.
reduce(lambda acc,x: (acc+x[1] if x[0]%2 else acc*x[1]), enumerate(numbers), 1)
We need to add odd number of elements and multiply even number of elements with previous elements.
This was a tough problem because you wanted to use everything in reduce. So just use reduce twice!
reduce(lambda x, y: x + y, reduce(lambda x, y: (x[0], x[1] + y[1]) if y[0]%2==1 else (x[0], x[1]*y[1]) , enumerate(a)))

Why does using "and" between two lists give me the second list (as opposed to an error)? [duplicate]

This question already has answers here:
Python AND operator on two boolean lists - how?
(10 answers)
Closed 5 years ago.
I encountered a bug in some code. The (incorrect) line was similar to:
[x for x in range(3, 6) and range(0, 10)]
print x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
(the correct way of writing this statement is not part of the question)
Wondering what someList and someOtherList does, I experimented. It seems to only ever set the result to the last parameter passed:
x = range(0,3) # [0, 1, 2]
y = range(3, 10) # [3, 4, 5, 6, 7, 8, 9]
z = range(4, 8) # [4, 5, 6, 7]
print x and y # [3, 4, 5, 6, 7, 8, 9]
print y and x # [0, 1, 2]
print z and y and x # [0, 1, 2]
I would assume that this is an unintentional consequence of being able to write something that is useful, but I'm not really seeing how the semantics of the "and" operator are being applied here.
From experience, python won't apply operators to things that don't support those operators (i.e. it spits out a TypeError), so I'd expect an error for and-ing something that should never be and-ed. The fact I don't get an error is telling me that I'm missing... something.
What am I missing? Why is list and list an allowed operation? And is there anything "useful" that can be done with this behaviour?
The and operator checks the truthiness of the first operand. If the truthiness is False, then the first argument is returned, otherwise the second.
So if both range(..)s contain elements, the last operand is returned. So your expression:
[x for x in range(3, 6) and range(0, 10)]
is equivalent to:
[x for x in range(0, 10)]
You can however use an if to filter:
[x for x in range(3, 6) if x in range(0, 10)]
In python-2.7 range(..) however constructs a list, making it not terribly efficient. Since we know that x is an int, we can do the bounds check like:
[x for x in range(3, 6) if 0 <= x < 10]
Of course in this case the check is useless since every element in range(3,6) is in the range of range(0,10).

How to debug in this simple Python homework?

I need a little bit of help with a homework problem for school using python. The prompt is pretty simple, but I can't seem to figure it out.
'''
rem(A,B) returns the list
[A[0]%B[0], A[1]%B[1], ...] etc
>>> rem( (10,20,30), (7,8,9) )
[3, 4, 3]
>>> X = [ i for i in range(10,18) ]
>>> Y = [ j+3 for j in range(8) ]
>>> rem(X,Y)+["?"]
[1, 3, 2, 1, 0, 7, 7, 7, '?']
>>> rem( [5,3], [3,2] )
[2, 1]
>>> rem( [10,9], [5,4] )
[0, 1]
'''
I have created this snippet of code which sort of works but not quite:
def rem(A,B):
return [A[0] % b for b in B]
Right now the definition is working, but only for the first value in each sequence. I think this is due to the A[0] - I need some way to make it do A[x+1], but I'm not sure. Also I'm pretty sure that I have to use range() somewhere in the definition as well.
You need to pair up each element of A with its corresponding element in B, and then mod them.
[x % y for (x, y) in zip(A, B)]
Ignacio's answer is correct and the most pythonic, this is the more basic way:
def rem(a,b):
l = []
for x in range(len(a)):
l.append(a[x]%b[x])
return l
See comments too!

Categories

Resources