Difference between [range(5)] and list(range(5)) - python-3.x

I'm trying to make a list through a range() using 2 different methods,
When I run it in python terminal, it return False
list(range(5))==[range(5)]
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> [range(5)]
[range(0, 5)]
I expect the output of [range(5)] = [0, 1, 2, 3, 4],
but it was [range(0, 5)]

list() is a function call, it takes an iterator as input and converts it into a list.
[] simply wraps whatever we put inside the bracket with a list.
So counter to your example, list(32) will throw an error but [32] will make a list with 32 as its element.

Related

How can I get multiple output variables into a list?

I'm wondering if there's a way of getting multiple outputs from a function into a list. I'm not interested in creating a list inside of a function for reasons I'm not going to waste your time going into.
I know how many output variables I am expecting, but only through using the annotations["return"] expression (or whatever you call that, sorry for the noobish terminology) and this changes from case to case, which is why I need this to be dynamic.
I know I can use lists as multiple variables using function(*myList), but I'm interested in if there's a way of doing the equivalent when receiving return values from a function.
Cheers!
Pseudocode:
function():
x = 1
y = 2
return x, y
variables = function()
print(variables[0], " and ", variables[1]
result should be = "1 and 2"
yes, with the unpacking assignments expression ex a,b,c= myfunction(...), you can put * in one of those to make it take a variable number of arguments
>>> a,b,c=range(3) #if you know that the thing contains exactly 3 elements you can do this
>>> a,b,c
(0, 1, 2)
>>> a,b,*c=range(10) #for when you know that there at least 2 or more the first 2 will be in a and b, and whatever else in c which will be a list
>>> a,b,c
(0, 1, [2, 3, 4, 5, 6, 7, 8, 9])
>>> a,*b,c=range(10)
>>> a,b,c
(0, [1, 2, 3, 4, 5, 6, 7, 8], 9)
>>> *a,b,c=range(10)
>>> a,b,c
([0, 1, 2, 3, 4, 5, 6, 7], 8, 9)
>>>
additionally you can return from a function whatever you want, a list, a tuple, a dict, etc, but only one thing
>>> def fun():
return 1,"boo",[1,2,3],{1:10,3:23}
>>> fun()
(1, 'boo', [1, 2, 3], {1: 10, 3: 23})
>>>
in this example it return a tuple with all that stuff because , is the tuple constructor, so it make a tuple first (your one thing) and return it

Are there any difference between Y and *Y, where Y is a list used as input argument?

I was using the torch.tensor.repeat()
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
period = x.size(1)
repeats = [1,2]
result = x.repeat(*repeats)
the result is
tensor([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
if I get result as follows
result = x.repeat(repeats)
the result is the same
tensor([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
It seems that x.repeat(repeats) and x.repeat(*repeats) work the same.
Does it mean that, for an input parameter, e.g, Y, I can use either Y or *Y
Kinda. If repeats is a (list or tuple) of ints, then it is equivalent. But in general the rule appears to be:
If the first argument is a list or tuple, take that as repeats. Ignore all other arguments.
Otherwise, take the full *args as repeats
So if your repeats is something weird like repeats=((1,2),(3,4)), then a.repeat(*repeats) succeeds and is the same as a.repeat(1, 2)==a.repeat((1, 2)) and a.repeat(repeats) fails.
Note: This is observational based on my own tests. The only official documentation is the defined type of the function, e.g. repeat(torch.Size or int...) which isn't perfectly clear with regards to semantics.
You can also get error messages like this:
TypeError: repeat(): argument 'repeats' (position 1) must be tuple of ints, not tuple
when you pass floats. In general error reporting could be better.

Obtain sum of subsets using recursion

I am working on a code to identify subsets of an array with sum of the elements in subsets equal to a given number, k. Here is the recursive code I attempted.
First approach:
def subset_sum(arr,curr,k,idx):
if idx==len(arr):
print(curr) //print the current subset for debugging
if sum(curr)==k:
print(curr)
return
subset_sum(arr,curr,k,idx+1) //exclude the element
curr.append(arr[idx]) //include the element
subset_sum(arr,curr,k,idx+1) // make recursive call
Then this function has been called using;subset_sum([1,2,3],[],4,0), and we get following output;
[]
[3]
[3]
[3, 2]
[3, 2, 3]
[3, 2, 3, 1]
[3, 2, 3, 1, 3]
[3, 2, 3, 1, 3, 2]
[3, 2, 3, 1, 3, 2, 3]
It is being difficult to comprehend, why are the elements being duplicated above. After some brainstorming, I tried second approach below.
Second approach.
def subset_sum(arr,curr,k,idx):
cnt=0
if idx==len(arr):
if sum(curr)==k:
cnt+=1
print(curr,cnt)
return cnt
subset_sum(arr,curr,k,idx+1)
subset_sum(arr,curr+[arr[idx]],k,idx+1)
We call the function subset_sum([1,2,3],[],3,0,0). This gives the output as;
[1,2],1
[3],1
since 1+2 gives us the required sum 3. May I know what is wrong in updating the element curr as I did in the first approach; curr.append(arr[idx]). And why is that the second approach is working fine.

How do I multiply elements in a list and find the sum in a simple way without numpy, zip etc

I have to multiply the same index of two lists and then find the sum of that.
Please help me out! Thank you.
Try this,
>>> A=[2, 3, -6, 7, 10, 11]
>>> B=[1, 2, 3, 4, 5, 6]
>>> sum([x * y for x, y in zip(A, B)])
134
Let me explain what I did in my answer, I used zip() python Built-in Function and this is what documentation mention about it.
Make an iterator that aggregates elements from each of the iterables.
Returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. The iterator stops when the shortest input iterable is exhausted. With a single iterable argument, it returns an iterator of 1-tuples. With no arguments, it returns an empty iterator.
Little bit confusing, right? Check the below example:-
>>> A=[2, 3, -6, 7, 10, 11]
>>> B=[1, 2, 3, 4, 5, 6]
>>> zip(A,B)
<zip at 0x1fde73e6f88> # it display something like this (zip object)
>>> list(zip(A,B)) # for visualization purpose, convert zip object to list
[(2, 1), (3, 2), (-6, 3), (7, 4), (10, 5), (11, 6)]
I think you can get clear idea what happen inside zip() function. Then multiply each and every value in zip object using python List Comprehensions to answer your question more pythonic. So zip object now created for us a new value series using A and B list. We assigned those values for x and y, multiply them and save in list.
>>> [x * y for x, y in zip(A, B)]
[2, 6, -18, 28, 50, 66]
After all the steps we used sum() to calculate the Sum a list of numbers in Python.
>>> sum([2, 6, -18, 28, 50, 66])
134
That's all, if you didn't get anything please add a comment to this answer.
AB = [A[i] * B[i] for i in range(len(A))]
sum(AB)
Alternatively, try
AB = [value_ * B[i] for i, value_ in enumerate(A)]
sum(AB)
I believe you want this:
def lists(A,B):
C = 0
for i in range(len(A)):
C += (A[i] * B[i])
return C
Now you can call your method lists with lists A and B like this:
A=[2, 3, -6, 7, 10, 11]
B=[1, 2, 3, 4, 5, 6]
lists(A,B)
Which will return 134. Your code was wrong because of your indentation. You had put your return statement inside the for loop, so your code would return C value in the first iteration, which was 0 + 2*1.
with list comprehension:
A = [2, 3, -6, 7, 10, 11]
B = [1, 2, 3, 4, 5, 6]
print (sum([A[i]*B[i] for i in range(len(A))]))
output:
134
your code:
def lists(A, B):
C = 0
for i in range(len(A)):
C += (A[i] * B[i])
return C # <-----
A = [2, 3, -6, 7, 10, 11]
B = [1, 2, 3, 4, 5, 6]
print (lists(A,B))
NOTE: you need to put your return statement out of the for loop.
If return statement is reached during the execution of a function, it will exit from function, what does it mean in your case if you have return in your for loop, in first iteration return function will be reached and exit (you got result 2 because in first iteration yuo have 2*1)

How to replace every element in a given list to its square and not create a new list with the squares

I want to make a function that takes a list of integers and replaces the elements in the list with their respective squares.
I tried reassigning every element by virtue of its position (index) in the list, but for some reason the second element in the list gets squared twice.
def square_list(list1):
for i in list1:
list1[list1.index(i)] = i**2
print(list1)
square_list([1, 2, 3, 4, 5])
I expect the printed list to be [1, 4, 9, 16, 25] since the list I'm testing the function with is [1, 2, 3, 4, 5].
If a function is required to square list elements in-place, use it:
def square_list(list_1):
for i in range(len(list_1)):
list_1[i] = list_1[i]**2
my_list = [1, 2, 3, 4, 5]
square_list(my_list)
print(my_list)
Since the function doesn't return anything, square_list([1, 2, 3, 4, 5]) is useless.
Python's map built-in function is good for this, so you don't really have to write your own function.
l = [1, 2, 3, 4, 5]
l = list(map(lambda x: x**2, l))

Resources