Apply map on *args in Python where *args are lists - python

I want to get a list of lists consisting of only 0 and 1 and map the first element of the first list with the first element of the second list and so on.
My mapping function is this:
def intersect(*values):
result = values[0]
for idx in range(1, len(values)):
result = result << 1
result = result | values[idx]
return result
I'm trying to do this but it does not work:
def intersect_vectors(*vectors):
return list(map(intersect, zip(vectors)))
It would work if I would knew the number of vectors and would have a function like this:
def intersect_vectors(v1, v2, v3):
return list(map(intersect, v1,v2,v3))
Example:
intersect_vectors([1,1],[1,0],[0,1]) would return [6,5] which is [b110, b101]

You can explode your vectors with * and it will work the same:
def intersect_vectors(*vectors):
return list(map(intersect, *vectors))

The simplest solution is probably to delegate the functionality of transforming between a list and 'arguments' to a lambda:
return [list(map((lambda v: intersect(*v)), zip(vectors)))]

Related

How to dynamically assign an unknown number of list elements?

I have this code which works but it's a big function block of IF..ELIF..ELSE. Is there a way to unpack or dynamically assign two lists. The thing is, sometimes mylist could have less elements than 4.
Input:
mylist=['1','2','3','4']
flag=['a','b','c','d']
Output:
A string object like 'a=1/b=2/c=3/d=4/' OR 'a=1/b=2/c=3/' if mylist only has 3 elements.
My current method is just like:
def myoutput(mylist, flag):
if flag=='3':
out = f'a={mylist[0]}/b={mylist[1]}/c={mylist[2]}/'
else:
out = f'a={mylist[0]}/b={mylist[1]}/c={mylist[2]}/d={mylist[3]}/'
return out
I tried to zip the two list, but I do not know the next steps and it doesn't really work:
tag_vars={}
for i in range((zip(mylist,flag))):
tag_vars[f"mylist{i}"] = flag[i]
print(tag_vars)
I would use zip for this task following way
mylist=['1','2','3','4']
flag=['a','b','c','d']
out = ''.join(f'{f}={m}/' for f,m in zip(flag,mylist))
print(out)
output
a=1/b=2/c=3/d=4/
Note that I used f,m with zip so f and m are corresponding elements from flag and mylist. Disclaimer: this solution assumes flag and mylist have always equal lengths.
You can use zip like this:
for a, b in zip(alist, blist): ...
I modified myoutput function to return your desired output
mylist=['1','2','3','4']
flag=['a','b','c','d']
def myoutput(mylist, flag):
result = []
for elem, f in zip(mylist, flag):
result.append(f"{f}={elem}")
return "/".join(result)
print(myoutput(mylist, flag)) # a=1/b=2/c=3/d=4
print(myoutput(mylist[:3], flag)) # a=1/b=2/c=3

Can we return one dataframe and one variable from a function in python? [duplicate]

I would like to return two values from a function in two separate variables.
For example:
def select_choice():
loop = 1
row = 0
while loop == 1:
print('''Choose from the following options?:
1. Row 1
2. Row 2
3. Row 3''')
row = int(input("Which row would you like to move the card from?: "))
if row == 1:
i = 2
card = list_a[-1]
elif row == 2:
i = 1
card = list_b[-1]
elif row == 3:
i = 0
card = list_c[-1]
return i
return card
And I want to be able to use these values separately. When I tried to use return i, card, it returns a tuple and this is not what I want.
You cannot return two values, but you can return a tuple or a list and unpack it after the call:
def select_choice():
...
return i, card # or [i, card]
my_i, my_card = select_choice()
On line return i, card i, card means creating a tuple. You can also use parenthesis like return (i, card), but tuples are created by comma, so parens are not mandatory. But you can use parens to make your code more readable or to split the tuple over multiple lines. The same applies to line my_i, my_card = select_choice().
If you want to return more than two values, consider using a named tuple. It will allow the caller of the function to access fields of the returned value by name, which is more readable. You can still access items of the tuple by index. For example in Schema.loads method Marshmallow framework returns a UnmarshalResult which is a namedtuple. So you can do:
data, errors = MySchema.loads(request.json())
if errors:
...
or
result = MySchema.loads(request.json())
if result.errors:
...
else:
# use `result.data`
In other cases you may return a dict from your function:
def select_choice():
...
return {'i': i, 'card': card, 'other_field': other_field, ...}
But you might want consider to return an instance of a utility class (or a Pydantic/dataclass model instance), which wraps your data:
class ChoiceData():
def __init__(self, i, card, other_field, ...):
# you can put here some validation logic
self.i = i
self.card = card
self.other_field = other_field
...
def select_choice():
...
return ChoiceData(i, card, other_field, ...)
choice_data = select_choice()
print(choice_data.i, choice_data.card)
I would like to return two values from a function in two separate variables.
What would you expect it to look like on the calling end? You can't write a = select_choice(); b = select_choice() because that would call the function twice.
Values aren't returned "in variables"; that's not how Python works. A function returns values (objects). A variable is just a name for a value in a given context. When you call a function and assign the return value somewhere, what you're doing is giving the received value a name in the calling context. The function doesn't put the value "into a variable" for you, the assignment does (never mind that the variable isn't "storage" for the value, but again, just a name).
When i tried to to use return i, card, it returns a tuple and this is not what i want.
Actually, it's exactly what you want. All you have to do is take the tuple apart again.
And i want to be able to use these values separately.
So just grab the values out of the tuple.
The easiest way to do this is by unpacking:
a, b = select_choice()
I think you what you want is a tuple. If you use return (i, card), you can get these two results by:
i, card = select_choice()
def test():
....
return r1, r2, r3, ....
>> ret_val = test()
>> print ret_val
(r1, r2, r3, ....)
now you can do everything you like with your tuple.
def test():
r1 = 1
r2 = 2
r3 = 3
return r1, r2, r3
x,y,z = test()
print x
print y
print z
> test.py
1
2
3
And this is an alternative.If you are returning as list then it is simple to get the values.
def select_choice():
...
return [i, card]
values = select_choice()
print values[0]
print values[1]
you can try this
class select_choice():
return x, y
a, b = test()
You can return more than one value using list also. Check the code below
def newFn(): #your function
result = [] #defining blank list which is to be return
r1 = 'return1' #first value
r2 = 'return2' #second value
result.append(r1) #adding first value in list
result.append(r2) #adding second value in list
return result #returning your list
ret_val1 = newFn()[1] #you can get any desired result from it
print ret_val1 #print/manipulate your your result

List-Then-Eliminate implementation in Python

I'm trying to implement the List-Then-Eliminate algorithm using a dataset. However, I am getting the wrong vector space at the end. I am unable to figure out what the issue is.
Basically, I iterate through all the training instances. For each hypothesis, I use the last 5 bits to check if the training instance, x is the same and then compare the c(x)
Any assistance would be appreciated. Below is my code.
def gen_vector_space(k):
return [''.join(x) for x in itertools.product('01', repeat=k)]
#basically values from 0-65536 in binary
vector_space = gen_vector_space(pow(2,4))
for train_inst in train_data:
result = train_inst[-1]
d = train_inst[:-1]
for h in vector_space:
if h[-5:-1] == d:
if (h[-1] != result):
vector_space.remove(h)
print(len(vector_space))
I'd suggest an edit to the function that creates your vector space. Starting with your original function:
def create_space(k):
return [''.join(x) for x in itertools.product('01', repeat=k)]
When you call that function, you are completely iterating over that range to build the list, then iterating the list again to filter out values. Two approaches to fix that:
If statements in function
# Redefine your function to only return values that matter to you
def create_space(k, d, result):
"""
This will filter out your limits, takes result and d as params
"""
vector_space = []
for x in itertools.product('01', repeat=k):
if x[-5:-1]==d and x[-1]!= result:
vector_space.append(x)
return vector_space
# define k, d, and result here
vector_space = create_space(k, d, result)
Generator Approach
Or, the yield keyword will calculate values one at a time, so you are only iterating once:
def create_space(k):
for x in itertools.product('01', repeat=k):
yield x
vector_space = []
# define d and result here
for x in create_space(k):
if x[-5:-1]==d and x[-1]!= result:
vector_space.append(x)
The thing to note with either of these approaches is that I'm not editing an already established object while iterating over it. Instead, I've put the filtering on before the space is created, that way you get exactly what you want on the first go.

Collapse Generator in Python

So I have a function like this:
def demo_range(limit):
value = 0
while value < limit:
yield value
value = value + 1
and this
def demo_generator_to_list(generator):
return [x for x in range(generator)]
Now in the demo_generator_to_list(generator) I need to fill some code to collapse a generator to:
[0,1,2,3]
from
demo_generator_to_list(demo_range(4))
Just pass the generator to a list() call:
def demo_generator_to_list(generator):
return list(generator)
The list() function will iterate over the generator and add all results to a new list object.
You could still use a list comprehension, but then you don't use range():
return [x for x in generator]
This has no advantage over using list(); it is just slower.

Generate variables for return

I have to return many variables from my function:
a = 5
b = 6
c = 8
d = 6
...
return a,b,c,d,e,f,g,h
Problem is that I would like to do it through array to save a code lines:
for (...):
ar[x] = ... # For x = a,b,c,d,e, ...
But I have to return variables in format 'return a,b,c,d,e' and I do not want to write it as:
return ar[a], ar[b], ar[c], ...
So can I use a generator for it and how? Somethig like:
return item for item in len(ar)
When you are "returning multiple variables", you are actually just returning a tuple. You can do this:
return tuple(ar)
or even
return ar
Assuming, of course, that your array contains everything you want to return in the correct order, and only that.
It would be nice to see more code, but it is likely that if you can fill that list using a loop, then it's semantically a single value (a homogenous collection) anyway.
You can do this:
def func(x):
# do something
lis = (#your values)
return lis
a,b,c,d,e = func(x)
This will return the values as a tuple, and unpacked at the other end
Use a generator expression and tuple:
return tuple(ar[x] for x in (a,b,c,d,e))
If indexes are continuous then you can use slicing:
return tuple(ar[2:8]) #If `ar` is a already a tuple then remove the tuple call
If you want to return the whole tuple/list itself then simply return it as is:
return ar #or return tuple(ar)
Note that returning a tuple is not compulsory, more discussion on it here: Python: Return tuple or list?
def values():
a = 3
b = 5
c = 9
d = 3
e = 5
return(a, b, c, d, e)
a1 = values()
print list(a1)
and you can edit the above function to return the tuple of variables
tuple(a,b,c,d,e)

Categories