Pass several arguments to function from map() - python

For example, if I want to detect all odd numbers in an array and set them to zero, I can use:
def setToZeroIfOdd(n):
if n % 2 == 0:
pass
else:
return 0
numbers = range(1,1000)
numbers = map(setToZeroIfOdd, numbers)
which works like a charm.
But when I try something like
def setToZeroIfDivisibleBy(n, divisor):
if n % divisor == 0:
return 0
else:
pass
numbers = map(setToZeroIfDivisibleBy(divisor=3), numbers)
it expects two arguments. Likewise,
numbers = map(setToZeroIfDivisibleBy, numbers, divisor=3)
does not work. How can I pass that divisor argument from within map()?

You can use functools.partial to make partial functions
from functools import partial
def setToZeroIfDivisibleBy(n, divisor):
if n % divisor == 0:
return 0
else:
pass
numbers = range(1,1000)
numbers = map(partial(setToZeroIfDivisibleBy, divisor=3), numbers)

Try using lambda function
numbers = map(lambda n: setToZeroIfDivisibleBy(n, divisor=3), numbers)
And rather than pass did you mean return n?

You make a function which returns a function:
def setToZeroIfDivisibleBy(divisor):
def callback(n):
if n % divisor == 0:
return 0
else:
pass
return callback
numbers = map(setToZeroIfDivisibleBy(3), numbers)
BTW, you can entirely omit empty branches like else: pass; it doesn't do anything. Since it results in a None, I don't think that's what you want either. You probably want return n there instead.

Another approach, instead of using partial, is to supply an infinite (or at least, long enough) sequence of 2nd arguments for the two-argument function:
from itertools import repeat
numbers = map(setToZeroIfDivisibleBy, numbers, repeat(3))
In Python 2, map will append None as necessary to the shorter of the two sequences to make them the same length. Assuming that will cause problems (either because your function cannot handle None as an input value or you end up with an infinite loop), you can either use itertools.imap, which stops after exhausting the shorter sequence:
from itertools import imap, repeat
numbers = list(imap(setToZeroIfDivisibleBy, numbers, repeat(3)))
or pass the length of numbers as a second argument to repeat so that the two sequences are the same length.
from itertools import repeat
numbers = map(setToZeroIfDivisibleBy, numbers, repeat(3, len(numbers)))

Related

How to combine on if statment if int number equal to element in the list of int?

Let's say I want to random number, but the number cannot be i, or number that is already in the list. How can I check against my list in the if statement?
I think I'm close to the answer:
if randlink == i or (randlink == x for x in listofnumbers):
return randNumber(i, listofnumbers)
This function returns a number that did not appear before, this is the code:
def randNumber(i, listofnumbers):
from random import randrange
randlink = randrange(0, size)
if randlink == i or [randlink == x for x in listofnumbers]:
return randNumber(i, listofnumbers)
return randlink
You can check if it is in your list using
if randlink in listofnumbers:
The operator you are looking for is in:
if randlink == i or randlink in listofnumbers:
...
Recursion is a bad idea in this case, since your code may search for a long time. Use a loop instead:
randlink = randrange(0, size)
while randlink == i or randlink in listofnumbers:
randlink = randrange(0, size)
return randlink
Don't use a list, since it has linear lookup. Use a set instead:
s = set(listofnumbers)
Do this once outside the function. The interface for lookup is the same:
while randlink == i or randlink in s:
Finally, sampling with rejection is generally not optimal. A better way is to figure out how map your sampling to the range you want.
In your code, you don't show an explicit correlation between i, listofnumbers, and size. You hint that this is some sort of attempt at sampling without replacement over a large range that you don't want to instantiate. The function random.sample was created for this exact purpose. If you pass in range(size) as the sequence, you will only need to allocate the samples that are actually picked, no matter how big size is.
Let's say that you want to generate n samples, and i is a random number you want to avoid. The contract of random.sample is that any subset has the same uniformity, so you can do the following:
numbers = set(random.sample(range(size), n + 1))
try:
numbers.remove(i)
except KeyError:
numbers.pop()
If you really want to preserve the original order as returned by random.sample, you can do it with a little more work:
numbers = random.sample(range(size), n + 1)
try:
numbers.remove(i)
except ValueError:
numbers.pop()
The list interface is almost identical to a set in this case, but much slower. The only difference is the exception type.

How to get minimum odd number using functions from list

I'm trying to get the minimum odd number using python. I used lambda, loops and other methods to get minimum odd number but i was not able to get that using functions. here is my code
z= [1,8,-4,-9]
def min_odd(x):
for i in x:
if (i%2!=0):
return min(i)
y = min_odd(z)
print (y)
Can some please tell me what i was missing here.
The min() function expects an iterable like a list which it will then yield the smallest element from.
E.g. min([1,0,3]) gives 0.
So if you want to use it, you must create a list (or other iterable) of the odd numbers that you can then pass into it:
def min_odd(x):
odds = []
for i in x:
if i % 2 != 0:
odds.append(i)
return min(odds)
note that we could also use a list-comprehension:
def min_odd(x):
return min([i for i in x if i % 2 != 0])
which both work.
An alternative method would be to store the current minimum odd value in a variable and update this variable if we come across a smaller odd value:
def min_odd(x):
min_v = float('inf')
for i in x:
if i % 2 != 0 and i < min_v:
min_v = i
return min_v
Try:
min([val for val in z if val % 2 != 0])
It seems your code logics are wrong. First off, you seem to have an indentation error in the return statement. Second off, the min() function requires a collection of items (like an array for example) or a series of arguments to determine the minimum in that series. You can try multiple things.
Use another variable to store a temporary minimum. Replace it every time you find a smaller odd value ( for every i in x... if the value is odd and is smaller than the previous odd value, replace it) and have it started with the first odd number you can find.
Take all the odd numbers and add them to another array on which you will apply the min function.
Hope this proves useful!
You could pass a generator into the min() function:
def min_odd(iterable):
return min(i for i in iterable if i % 2)
I didn't write i % 2 != 0 because any odd number will return 1 which has a Boolean value of True.
I added a parameter to the function that takes the iterable so it can be used for any iterable passed in.
min operates on an iterable. i is not an iterable in your code; it's the last element of the list.
You can achieve what you want with a filter, though:
min(filter(lambda e: e%2 != 0, x))

Delete elements of an integer recursively

My parameter, n is a phone number as an integer.
Using recursion I want to return the first three numbers in the integer.
I've turned the integer into a list of individual number characters and I'm attempting to delete the last number over and over again until I'm left with the last three, but I'm stuck on how to repeat it.
def areaCodes(n):
n = str(n)
n = list(n)
del n[-1]
#n = reduce(opperator.add, n)
n = ''.join(n)
n = int(n)
return n
I know I'm supposed to repeat the name in the return somehow, but because n isn't an integer that I can use to repeat. What do I do?
How about something like this?
def areaCodes(n):
# if n is less than 1000, what does it mean about the number of digits?
if n < 1000:
return # fill...
# otherwise, if n is greater than 1000, how can we alter n to remove the last
# digit? (hint: there's an operation similar to division called f...r division)
return areaCodes( # operate on n somehow...)
I assume that this is an exercise where recursion is necessary. If so, try this (there are better ways to accomplish your end goal, but I tried to modify your existing code as little as possible):
def areaCodes(n):
n_lst = list(str(n))
del n_lst[-1]
n_str = ''.join(n_lst)
n_int = int(n_str)
if len(n_lst) > 3:
return areaCodes(n_int)
return n_int
This will call the function again if the length of the number is greater than three, and return the number otherwise. Basically, the only part you were missing in your original function was the following, which is the recursive part:
if len(n_lst) > 3:
return areaCodes(n_int)
Remember that for a function to be recursive, it will have two main attributes:
It will at some point call itself. (this is what makes it 'repeat')
It will have some stopping condition (or base case).
You mentioned #1 when you wrote that you're supposed to use "the name in the return," so that's great! You just need to write that in your code:
return areaCodes(n), Where n is the updated phone number with a digit removed.
As you can see, each recursive call should do some work towards the solution, and should pass its mini-solution to the next recursive call.
Along with #2 above, you need to specify a base case, where the recursion will cease. So, since you're taking away a digit each time you call your function, you should include some kind of check to see if the current input is the length you want yet.
If it is the right length, you're done, and you should return the current number (not another recursive call).
Otherwise, you aren't done with the recursion yet.
import sys
def areaCodes(n):
#Create a list
myList = list(str(n))
#Delete last element
del myList[-1]
#Combine your elements into string list
myListStr = ''.join(myList)
#Type cast to int
myListInt = int(myListSte)
#Check whether your list satisfies your condition
if len(myList) > 3:
#Recusivley call the function again
return areaCodes(myListInt)
#Return your list when recursion completes
return myListInt
n = 12345
print areaCodes(n)

How to run down a list with recursion?

At first, I had to do it without recursion (just by looping which is pretty easy).
Now I have to do it with recursion, but I am not allowed to use any loop.
I guess I have to run down the list with recursion, but I don't quite understand what should be my base, or the reduction...
def long_strings_rec(strings, N):
'''
strings - a list of strings
N - an integer
Returns all strings in 'strings' of length bigger then 'N'
(This function is recursive and does not use loops)
'''
# Your code for question #2 (second function) starts here
# Your code for question #2 (second function) ends here
Any ideas? Can I have maybe an example of how to use recursion to take actions on lists indexes?
I used the helper function to do that, like #7stud suggested:
def helper (strings, K, results):
if len(strings) == 0:
return 0
elif len(strings[0]) > K:
results.append(strings[0])
strings.pop(0)
else:
strings.pop(0)
helper(strings, K, results)
return results
def long_strings_rec (strings, N):
'''
strings - a list of strings
N - an integer
Returns all strings in 'strings' of length bigger then 'N'
(This function is recursive and does not use loops)
'''
# Your code for question #2 (second function) starts here
return helper(strings, N, [])
# Your code for question #2 (second function) ends here
Worked like a charm. Hope it's not buggy.
Here's an example of how to use an accumulator:
def sum(nums):
return helper(nums, 0) #0 is the initial value for the accumulator
def helper(nums, total): #total is the accumulator
if len(nums) == 0:
return total
else:
num = nums.pop()
return helper(nums, total+num)
print sum([1, 2, 3])
--output:--
6
Basically, you redefine sum() so that it takes an additional accumulator parameter variable, then have sum() call the new function.
See if you can apply those principles to your problem.
As bjorn pointed out in the comments, you could do it like this too:
def mysum(nums, total=0):
if len(nums) == 0:
return total
else:
num = nums.pop()
return sum(nums, total+num)
print mysum([1, 2, 3])
--output:--
6

Modulus on a list, doable?

I'm trying to create a program which checks if the number is a prime number. My idea was to use the function that the square root of the number, divided by all numbers up to the square root defines if the number is a prime or not. (I hope you understand)
Anyway, I'm trying to find a way to use modulus on every character in my list. As an example
Prime % List(2,sqrtPrime) =/ 0 #I know this doesnt work, just a hint how i want it to work.
As the error if I run this is that I cant use modulus on a list, so how do i do it?
And also, will this idea go through every character from 2-sqrtPrime?
Thanks
What seems the optimal way to me, would look like:
rng = xrange(2, int(math.sqrt(n)) + 1)
is_prime = all(n % i for i in rng)
Main points are:
rng is a generator, not a list
expression within (...) is a generator as well, so no unnecessary intermediate lists are created
all will stop iterating as soon as the first divisor is found, thus no extra iterations
You could write a function that returns True if its argument is Prime and otherwise False, then run filter on the list.
import math
def isPrime(x):
for factor in range(2,math.floor(x**0.5)+1):
if x % factor == 0:
# x divides evenly, so
return False
return True
lst = [some, numbers, go, here]
primes_in_lst = filter(isPrime, lst)
Or if you're against filter as a rule (some people contend it's unpythonic) then you can put it in a list comp.
primes_in_lst = [num for num in lst if isPrime(num)] # exactly equivalent
and technically that isPrime function could be a lambda:
primes_in_lst = filter(lambda x: all(x%factor for factor in range(2,math.floor(x**0.5)+1)), lst)
But jeebus that's ugly.

Categories

Resources