Multiply odd indices by 2? - python

So I'm writing a function that is going to multiply each number at an odd index in a list by 2. I'm stuck though, as I really don't know how to approach it.
This is my code.
def produkt(pnr):
for i in pnr:
if i % 2 != 0:
i = i * 2
return pnr
If I, for example, type produkt([1,2,3]) I get [1,2,3] back but I would want it to be [2,2,6].

note that modifying i in your example does not change the value from the input list (integers are immutable). And you're also mixing up the values with their position.
Also, since indices start at 0 in python, you got it the wrong way.
In those cases, a simple list comprehension with a ternary expression will do, using enumerate to be able to get hold of the indices (making it start at 1 to match your case, you can adjust at will):
[p*2 if i%2 else p for i,p in enumerate(pnr,1)]
(note if i%2 is shorter that if i%2 != 0)

using list comprehensions:
multiply odd numbers by 2:
[x*2 if x%2 else x for x in pnr]
After clarification of question wording:
multiply numbers at odd indices by 2:
[x*2 if i%2 else x for i,x in enumerate(pnr)]

Consider using list comprehensions:
def produkt(pnr):
return [k * 2 if k % 2 else k for k in pnr]
Doing i = i * 2 you just override a local variable.
UPDATE (question was changed):
def produkt(pnr):
return [k * 2 if i % 2 else k for i, k in enumerate(pnr, 1)]

You can get the indices using enumerate, however that starts by default with index 0 (not 1) but it accepts a start argument to override that default.
The problem with your approach is that you don't change the actual list contents, you just assign a different value to the name i (which represented a list element until you assigned a different value to it with i = i*2). If you want it to work in-place you would need to modify the list itself: e.g. pnr[idx] *= 2 or pnr[idx] = pnr[idx] * 2.
However, it's generally easier to just create a new list instead of modifying an existing one.
For example:
def produkt(pnr):
newpnr = [] # create a new list
for idx, value in enumerate(pnr, 1):
# If you're testing for not-zero you can omit the "!=0" because every
# non-zero number is "truthy".
if idx % 2:
newpnr.append(value * 2) # append to the new list
else:
newpnr.append(value) # append to the new list
return newpnr # return the new list
>>> produkt([1,2,3])
[2, 2, 6]
Or even better: use a generator function instead of using all these appends:
def produkt(pnr):
for idx, value in enumerate(pnr, 1):
if idx % 2:
yield value * 2
else:
yield value
>>> list(produkt([1,2,3])) # generators should be consumed, for example by "list"
[2, 2, 6]
Of course you could also just use a list comprehension:
def produkt(pnr):
return [value * 2 if idx % 2 else value for idx, value in enumerate(pnr, 1)]
>>> produkt([1,2,3])
[2, 2, 6]

Try this:
def produkt(pnr):
return [ 2*x if i % 2 == 0 else x for i, x in enumerate(pnr)]
It will double every element in your list with an odd index.
>>> produkt([1,2,3])
[2, 2, 6]

Your code does not work, as i is no reference to the value inside the list, but just its value.
You have to store the new value in the list again.
def produkt(pnr):
for i in range(len(pnr)):
if pnr[i] % != 0:
pnr[i] *= 2
return pnr
or use this more convenient solution:
def produkt(pnr):
return [x * 2 if x % 2==0 else x for x in pnr]
Edit: As the question has been changed (completely) you should use this code:
def produkt(pnr):
return [x * 2 if ind % 2 else x for ind, x in enumerate(pnr)]
The first examples multiply each odd index by 2 and the former code multiplies the numbers at odd indices by 2.

Your problem is that i is a copy of the values in the pnr list, not the value in the list itself. So, you are not changing the list when doing i = i * 2.
The existing answers are already good and show the idiomatic way to achieve your goal. However, here is the minimum change to make it work as expected for learning purpose.
produkt(pnr):
new_pnr = list(pnr)
for ix in len(new_pnr):
if new_pnr[ix] % 2 != 0:
new_pnr[ix] *= 2
return new_pnr
Without new_pnr you'd be changing the list in place and then you wouldn't need to return it.

Related

If the input number is in the list add its index to a new one

I want to check if the input number is in the list, and if so - add its index in the original list to the new one. If it's not in the list - I want to add a -1.
I tried using the for loop and adding it like that, but it is kind of bad on the speed of the program.
n = int(input())
k = [int(x) for x in input().split()]
z = []
m = int(input())
for i in range(m):
a = int(input())
if a in k: z.append(k.index(a))
else: z.append(-1)
The input should look like this :
3
2 1 3
1
8
3
And the output should be :
1
-1
2
How can I do what I'm trying to do more efficiently/quickly
There are many approaches to this problem. This is typical when you're first starting in programming as, the simpler the problem, the more options you have. Choosing which option depends what you have and what you want.
In this case we're expecting user input of this form:
3
2 1 3
1
8
3
One approach is to generate a dict to use for lookups instead of using list operations. Lookup in dict will give you better performance overall. You can use enumerate to give me both the index i and the value x from the list from user input. Then use int(x) as the key and associate it to the index.
The key should always be the data you have, and the value should always be the data you want. (We have a value, we want the index)
n = int(input())
k = {}
for i, x in enumerate(input().split()):
k[int(x)] = i
z = []
for i in range(n):
a = int(input())
if a in k:
z.append(k[a])
else:
z.append(-1)
print(z)
k looks like:
{2: 0, 1: 1, 3: 2}
This way you can call k[3] and it will give you 2 in O(1) or constant time.
(See. Python: List vs Dict for look up table)
There is a structure known as defaultdict which allows you to specify behaviour when a key is not present in the dictionary. This is particularly helpful in this case, as we can just request from the defaultdict and it will return the desired value either way.
from collections import defaultdict
n = int(input())
k = defaultdict(lambda: -1)
for i, x in enumerate(input().split()):
k[int(x)] = i
z = []
for i in range(n):
a = int(input())
z.append(k[a])
print(z)
While this does not speed up your program, it does make your second for loop easier to read. It also makes it easier to move into the comprehension in the next section.
(See. How does collections.defaultdict work?
With these things in place, we can use, yes, list comprehension, to very minimally speed up the construction of z and k. (See. Are list-comprehensions and functional functions faster than “for loops”?
from collections import defaultdict
n = int(input())
k = defaultdict(lambda: -1)
for i, x in enumerate(input().split()):
k[int(x)] = i
z = [k[int(input())] for i in range(n)]
print(z)
All code snippets print z as a list:
[1, -1, 2]
See Printing list elements on separated lines in Python if you'd like different print outs.
Note: The index function will find the index of the first occurrence of the value in a list. Because of the way the dict is built, the index of the last occurrence will be stored in k. If you need to mimic index exactly you should ensure that a later index does not overwrite a previous one.
for i, x in enumerate(input().split()):
x = int(x)
if x not in k:
k[x] = i
Adapt this solution for your problem.
def test(list1,value):
try:
return list1.index(value)
except ValueError as e:
print(e)
return -1
list1=[2, 1, 3]
in1 = [1,8,3]
res= [test(list1,i) for i in in1]
print(res)
output
8 is not in list
[1, -1, 2]

Is it possible to limit the length of a conditional list comprehension in Python?

I am doing a conditional list comprehension e.g. newlist = [x for x in list if x % 2 == 0]. I want to limit the length of the resulting list to a specific number.
Is this possible without first comprehending the entire list and then slicing it?
I imagine something that has the functionality of:
limit = 10
newlist = []
for x in list:
if len(newlist) > limit:
break
if x % 2 == 0:
newlist.append(x)
Slicing the original list (e.g. [x for x in list[:25] if x % 2 == 0] is not possible, as the if condition does not return True in any predictable intervals in my specific use case.
Many thanks in advance.
Please don't name any variables list as it shadows the built-in list constructor. I used li as a replacement for the input list here.
import itertools as it
gen = (x for x in li if x % 2 == 0) # Lazy generator.
result = list(it.islice(gen, 25))
Since you are creating a list with the list comprehension you can slice your list directly after it is created.
[x for x in list[:25] if x % 2 == 0][:limit]

Python list: if a pair of numbers equals 0 return the positions of the elements

I am trying to write a python functions that takes in a list or array. if any two numbers in the list or array equal to zero, I want to return the positions of those two numbers.
Here is what I have so far. I loop through the list and have a nested loop of the same list to test if the outer iterator plus the nested iterator == 0: if yes then I am trying to return the positions of the two numbers that == 0. but it just gives me the actual two numbers instead. whats strange is the output below (even though it is not what I want) should be (3,-3). Any input would be greatly appreciated
def twosum(nums):
for x in nums:
for y in nums:
if x + y == 0:
return nums[x],nums[y]
print twosum([1, 3, 5, -3])
output = (-3, 3)
You have to use enumerate() while iterating over the list like:
def twosum(nums):
for i, x in enumerate(nums):
for j, y in enumerate(nums):
if x + y == 0:
return i, j
However this logic can be further optimised as:
def twosum(nums):
for i, x in enumerate(nums):
if -x in nums[i:]: # check '-'ive of the number in non-iterated list
return x, -x
You would do return nums.index(x), nums.index(y)

Remove an even/odd number from an odd/even Python list

I am trying to better understand list comprehension in Python. I completed an online challenge on codewars with a rather inelegant solution, given below.
The challenge was:
Given a list of even numbers and one odd, return the odd
Given a list of odd numbers and one even, return the even
My (inelegant) solution to this was:
def find_outlier(integers):
o = []
e = []
for i in integers:
if i % 2 == 0:
e.append(i)
else:
o.append(i)
# use sums to return int type
if len(o) == 1:
return sum(o)
else:
return sum(e)
Which works fine, but seems to be pretty brute force. Am I wrong in thinking that starting (most) functions with placeholder lists like o and e is pretty "noob-like"?
I would love to better understand why this solution works for the odd list, but fails on the even list, in an effort to better understand list comprehension:
def find_outlier(integers):
if [x for x in integers if x % 2 == 0]:
return [x for x in integers if x % 2 == 0]
elif [x for x in integers if x % 2 != 0]:
return [x for x in integers if x % 2 != 0]
else:
print "wtf!"
o = [1,3,4,5]
e = [2,4,6,7]
In[1]: find_outlier(o)
Out[1]: [4]
In[2]: find_outlier(e)
Out[2]: [2, 4, 6]
Where Out[2] should be returning 7.
Thanks in advance for any insights.
Your attempt fails because the first if is always going to be true. You'll always have a list with at least 1 element; either the odd one out is odd and you tested a list with all even numbers, otherwise you have a list with the one even number in it. Only an empty list would be false.
List comprehensions are not the best solution here, no. Try to solve it instead with the minimum number of elements checked (the first 2 elements, if they differ in type get a 3rd to break the tie, otherwise iterate until you find the one that doesn't fit in the tail):
def find_outlier(iterable):
it = iter(iterable)
first = next(it)
second = next(it)
parity = first % 2
if second % 2 != parity:
# odd one out is first or second, 3rd will tell which
return first if next(it) % 2 != parity else second
else:
# the odd one out is later on; iterate until we find the exception
return next(i for i in it if i % 2 != parity)
The above will throw a StopIteration exception if there are either fewer than 3 elements in the input iterable, or there is no exception to be found. It also won't handle the case where there is more than one exception (e.g. 2 even followed by 2 odd; the first odd value would be returned in that case).
What are the shortcomings of this response (which is at the top of the solution stack on this particular challenge)?
def find_outlier(int):
odds = [x for x in int if x%2!=0]
evens= [x for x in int if x%2==0]
return odds[0] if len(odds)<len(evens) else evens[0]
The most efficient answer is going to get a little ugly.
def f(in_list):
g = (i for i in in_list)
first = next(g)
second = next(g) #The problem as described doesn't make sense for fewer than 3 elements. Let them handle the exceptions.
if first%2 == second%2:
a = first%2
for el in g:
if el%2 != a:
return el
else:
third = next(g)
if third%2 == first%2:
return second
else:
return first
except ValueError('Got a bad list, all evens or all odds')

Multiply every other element in a list

I have a list, let's say: list = [6,2,6,2,6,2,6], and I want it to create a new list with every other element multiplied by 2 and every other element multiplied by 1 (stays the same).
The result should be: [12,2,12,2,12,2,12].
def multi():
res = 0
for i in lst[0::2]:
return i * 2
print(multi)
Maybe something like this, but I don't know how to move on from this. How is my solution wrong?
You can use slice assignment and list comprehension:
l = oldlist[:]
l[::2] = [x*2 for x in l[::2]]
Your solution is wrong because:
The function doesn't take any arguments
res is declared as a number and not a list
Your loop has no way of knowing the index
You return on the first loop iteration
Not related to the function, but you didn't actually call multi
Here's your code, corrected:
def multi(lst):
res = list(lst) # Copy the list
# Iterate through the indexes instead of the elements
for i in range(len(res)):
if i % 2 == 0:
res[i] = res[i]*2
return res
print(multi([12,2,12,2,12,2,12]))
You can reconstruct the list with list comprehenstion and enumerate function, like this
>>> [item * 2 if index % 2 == 0 else item for index, item in enumerate(lst)]
[12, 2, 12, 2, 12, 2, 12]
enumerate function gives the current index of them item in the iterable and the current item, in each iteration. We then use the condition
item * 2 if index % 2 == 0 else item
to decide the actual value to be used. Here, if index % 2 == 0 then item * 2 will be used otherwise item will be used as it is.

Categories