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]
Related
Sorry If this has already been asked but I can't seem to find the answer I'm looking for, they all have involved using tools we aren't allowed to use yet.
The question is I have to use a for loop to go through a list and find the minimum value and then return the index of that value. That part I'm okay with, the issue I'm having is how do I get the program to return all the occurrences of that min value?
Restrictions
I can't use anything like enumerate or other such functions, I'm allowed to use the min function but that's it and it has to be done within a for loop.
Any help would be appreciated, thanks!
n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
for i in n:
min_val = []
item = min(n)
item_index = n.index(item)
min_val.append(item_index)
print(min_val)
I'm assuming this is python so you can use numpy
import numpy as np
n = np.array([1, 2, 3, -50, -60, 0, 6, 9, -60, -60])
searchKey = -60
item_index = np.where(n == searchKey)[0]
item_index => array([4, 8, 9])
if you don't know the minimum value ahead of time you can use a for-loop like this:
minval = n[0]
for i in n:
if i < minval:
minval = i
then just replace searchKey with minval above
disclaimer: n is of type np.array not list, not sure if this matters to you but if so I can post a less eloquent list solution that doesn't use enumerate.
Here is the solution to this:
n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
for i in n:
min_count = n.count(min(n)) # getting a count of the number of minimum values
min_value = min(n)
min_index_list = []
for j in range(min_count):
min_index = n.index(min_value)
min_index_list.append(min_index)
n[min_index] += 1
break
print(min(n) - 1, min_index_list)
The following list Comprehension will do the work in one line
min_val_idxs = [ x for x in range(len(n)) if n[x] == min(n)]
Using a for-loop:
create an empty list, indices
this is done before / outside of the loop, otherwise the list is reset with each iteration.
create the loop with for i in range(len(x)):, which essentially iterates through a list of index locations [0, 1, 2, 3, ..., len(x)-1]
for i in n: just iterates through each value in your list
in the loop, add any i, where x[i] is a match to min(x), to the list
def get_indices(x: list) -> list:
indices = list()
min_val = min(x)
for i in range(len(x)):
if x[i] == min_val:
indices.append(i)
return indices
print(get_indices(n))
>>> [4, 8, 9]
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]
In Python 2.7, I have two lists of integers:
x = [1, 3, 2, 0, 2]
y = [1, 2, 2, 3, 1]
I want to create a third list which indicates whether each element in x and y is identical, to yield:
z = [1, 0, 1, 0, 0]
How can I do this using list comprehension?
My attempt is:
z = [i == j for i,j in ...]
But I don't know how to complete it.
You are looking for zip
z = [i == j for i,j in zip(x,y)]
But you better add int call to get your desired output
>>> z = [int(i == j) for i,j in zip(x,y)]
>>> z
[1, 0, 1, 0, 0]
else you'll get a list like [True, False, True, False, False]
As ajcr mentions in a comment, it is better to use itertools.izip instead of zip if the lists are very long. This is because it returns an iterator instead of a list. This is mentioned in the documentation
Like zip() except that it returns an iterator instead of a list.
demo
>>> from itertools import izip
>>> z = [int(i == j) for i,j in izip(x,y)]
>>> z
[1, 0, 1, 0, 0]
You can change it a little bit and do:
[x[i] == y[i] for i in xrange(len(x))]
If you use Python3 - change xrange to range
While a list comprehension was specified in the question and the answers above are probably better, I thought I'd chime in with a recursive solution:
def compare_lists(a, b, res=[]):
if len(a) == len(b):
if a == []:
return res
else:
if a[0] == b[0]:
res.append(1)
else:
res.append(0)
return compare_lists(a[1:], b[1:])
else:
return "Lists are of different length."
I am trying to convert a list that contains negative values, to a list of non-negative values; inverting the negative ones. I have tried abs but it didn't work.
My input is
x = [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
How can I make it into this format as I am trying calculate the area
x = [10,9,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,9,10]
Try a list comprehension:
x2 = [abs(k) for k in x]
Your attempt didn't work because abs() takes an integer, not a list. To do this, you'll have to either loop through the list:
x = [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
for i in range(len(x)):
x[i] = abs(x[i])
Or you can use list comprehension, which is shorter:
x = [abs(i) for i in x]
Or simply use the built-in map function, which is even shorter :)
x = list(map(abs, x))
Hope this helps!
The simple pythonic way is the list comprehension above but if you're using Numpy for anything else you could do:
x2 = numpy.abs(x)
with no need to convert or do any looping.
what you want is to use the absolute value (|x| = x if x > 0, |x| = -x if x < 0)
for index in range(len(x)):
x[index] = x[index] if x[index] > 0 else -x[index]
This is a wrong answer to your question, but this is what I came here looking for. This is how to invert all the numbers in your list using operator.neg; i.e. also positives to negatives.
import operator
x = [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
x = list(map(operator.neg, x))
It returns:
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Or you can do a list comprehension of course:
x = [-xi for xi in x]
There is this code:
lista = [3,4,5,2,1,6,8,3]
print lista # [3, 4, 5, 2, 1, 6, 8, 3]
lista.sort(cmp=lambda x,y: cmp(y,x)) # sort descending
print lista # [8, 6, 5, 4, 3, 3, 2, 1] -- it is sorted
lista = [3,4,5,2,1,6,8,3]
print lista # [3, 4, 5, 2, 1, 6, 8, 3]
lista.sort(cmp=lambda x,y: y > x) # sort descending
print lista # [3, 4, 5, 2, 1, 6, 8, 3] -- nothing happens
Why does the lambda function in the second block not sort the numbers?
The second example doesn't work because the function you're giving it isn't a valid comparator.
A valid comparator is supposed to
return a negative, zero or positive number depending on whether the
first argument is considered smaller than, equal to, or larger than
the second argument.
The function lambda x,y: y > x doesn't fulfil this contract.
A cmp function needs to return a negative or positive number to indicate which element should go first (unless they are equal, then return 0). Your cmp function of y > x will only return 0 or 1. Try changing it to the following:
lista.sort(cmp=lambda x,y: (y > x) - (y < x))
I took this from the Python 3 docs:
If you really need the cmp() functionality, you could use the expression (a > b) - (a < b) as the equivalent for cmp(a, b).
x < y returns True or False, while cmp returns 1 and -1. This code works:
lista.sort(cmp=lambda x,y: 1 if x<y else -1)