What does this Python code do? Explanation of brackets - python

Can you explain these lines?
I can't understand what's happening in brackets (j,pbase).
mults = {}
if c in mults:
(j,pbase) = mults.pop(c)

Unpacking a tuple:
(j,pbase) = mults.pop(c)
Is the same as:
x = mults.pop(c)
j = x[0]
pbase = x[1]

a,b = something
This means something is a sequence of two values. a is assigned to the first value, and b is assigned to the second.
This is called tuple unpacking.

the python .pop() function will remove the item at that index and then return whatever was deleted. this means that the element of mults at index c will be stored within j and pbase. the way this is written would suggest that each element of the list is a tuple or such. this would mean that the first item goes in j and the second in pbase.

Related

Display only 1 element when it's a repetition

I would like print a result without duplicate with my multiplication
Here an example :
5*3*2=30
2*3*5=30
5*2*3=30
3*2*5=30
.....
All these element are from my list that I browse and you can see it's always =30
So I would like display only the first element (5*3*2) and not others because they are the same.
To be more accurate, here an example what I have :
list = ['5*3*2','5*2*3','2*3*5','2*5*3']
for i in list:
if eval(i) == eval(i)+1 ??? (I dont know how to say the next element)
print(eval(i))
Thanks for reading
Something like this with not in will help you.
#python 3.5.2
list = ['5*3*2','5*2*3','6*9','2*3*5','2*5*3','8*3','9*6']
elm = []
for i in list:
elm_value = eval(i)
if elm_value not in elm:
elm.append(elm_value)
print(elm)
DEMO: https://rextester.com/QKV22875
The comparison:
eval(i) == eval(i)+1
Will compare if the the number i is equal to i + 1, which will always return False. I'm sure you mean to use i as an index and simply wanted to compare if the current element is equal to the next element in the list. However, doing this doesn't really keep track of duplicates, since you have to consider everything else in the list.
Its also not a good idea to use list as a variable name, since it shadows the builtin function list. Plenty of other suitable names you can use.
One way is to use a set to keep track of what items you have seen, and only print items that you have seen for the first time:
lst = ["5*3*2","5*2*3","2*3*5","2*5*3"]
seen = set()
for exp in lst:
calc = eval(exp)
if calc not in seen:
print(calc)
seen.add(calc)
If you are always dealing with simple multiplying expressions with the * operator(no brackets), you could also use functools.reduce and operator.mul instead to multiply the numbers instead of eval here. This will first split the numbers by *, map each number string to an integer, then multiply every element with each other.
from operator import mul
from functools import reduce
lst = ["5*3*2","5*2*3","2*3*5","2*5*3"]
seen = set()
for exp in lst:
numbers = map(int, exp.split("*"))
calc = reduce(mul, numbers)
if calc not in seen:
print(calc)
seen.add(calc)
Output:
30
With the following list:
l = ['5*3*2','5*2*3','2*3*5','2*5*3', '2*2']
(Note that list is already something in python so I wouldn't recommend using that as a variable name)
I would first create a list of unique values:
unique_vals = set(map(eval, list))
set([4, 30])
Then for each unique values get the first match in l:
[next(x for x in l if eval(x) == i) for i in unique_vals]
I get:
['2*2', '5*3*2']
Is that what you want?

Nested For Loop Copies the last line in set of indicies

for each in Dti:
i = 0
for each in Dti[0]:
xbi[t][i] = Dti[t][i]
print(t)
i = i + 1
t = t + 1
this is just a test that I'm doing to figure out why my complicated code isn't working. I'm trying to iterate through a list and then each value in the list to set a new list of lists equal to that value. I know I could just set them equal to each other, but it needs to be done this way for my more complicated program. Any tips? I'm getting Dti[-1] for each xbi[t]. I've tried with while too and got the same results
Try something like this:
for t, D in enumerate(Dti)
for i, d in enumerate(D):
xbi[t][i] = d
print(t)
You can use slicing in assignments to replace one list's elements with the elements of another list:
for t, row in enumerate(Dti):
xbi[t][:] = row

Returning the index of the largest element in an array in Python

I'm trying to create a function that returns the largest element of an array, I feel I have the correct code but my syntax is in the wrong order, I'm trying to use a for/while loop in order to do so. So far I have the following:
def manindex(arg):
ans = 0
while True:
for i in range (len(arg)):
if arg[i] > arg[ans]:
pass
ans = i
return ans
Not sure where I'm going wrong if anyone could provide some guidance, thanks
EDIT: So it's been pointing out I'm causing an infinite loop so if I take out the while statement I'm left with
def manindex(arg):
ans = 0
for i in range (len(arg)):
if arg[i] > arg[ans]:
ans = i
return ans
But I have a feeling it's still not correct
When you say array I think you mean list in Python, you don't need a for/loop or while/loop to achieve this at all.
You can also use index with max, like so:
xs.index(max(xs))
sample:
xs = [1,123,12,234,34,23,42,34]
xs.index(max(xs))
3
You could use max with the key parameter set to seq.__getitem__:
def argmax(seq):
return max(range(len(seq)), key=seq.__getitem__)
print(argmax([0,1,2,3,100,4,5]))
yields
4
The idea behind finding the largest index is always the same, iterating over the elements of the array, compare to the max value we have at the moment, if it's better, the index of the current element is the maximum now, if it's not, we keep looking for it.
enumerate approach:
def max_element_index(items):
max_index, max_value = None, None
for index, item in enumerate(items):
if item > max_value:
max_index, max_value = index, item
return max_index
functional approach:
def max_element_index(items):
return reduce(lambda x,y: x[1] > y[1] and x or y,
enumerate(items), (None, None))[0]
At the risk of looking cryptic, the functional approach uses the reduce function which takes two elements and decides what is the reduction. Those elements are tuples (index, element), which are the result of the enumerate function.
The reduce function, defined on the lambda body takes two elements and return the tuple of the largest. As the reduce function reduces until only one element in the result is encountered, the champion is the tuple containing the index of the largest and the largest element, so we only need to access the 0-index of the tuple to get the element.
On the other hand if the list is empty, None object is returned, which is granted on the third parameter of the reduce function.
Before I write a long winded explanation, let me give you the solution:
index, value = max(enumerate(list1), key=lambda x: x[1])
One line, efficient (single pass O(n)), and readable (I think).
Explanation
In general, it's a good idea to use as much of python's incredibly powerful built-in functions as possible.
In this instance, the two key functions are enumerate() and max().
enumerate() converts a list (or actually any iterable) into a sequence of indices and values. e.g.
>>> list1 = ['apple', 'banana', 'cherry']
>>> for tup in enumerate(list1):
... print tup
...
(0, 'apple')
(1, 'banana')
(2, 'cherry')
max() takes an iterable and returns the maximum element. Unfortunately, max(enumerate(list1)) doesn't work, because max() will sort based on the first element of the tuple created by enumerate(), which sadly is the index.
One lesser-known feature of max() is that it can take a second argument in the form max(list1, key=something). The key is a function that can be applied to each value in the list, and the output of that function is what gets used to determine the maximum. We can use this feature to tell max() that it should be ranking items by the second item of each tuple, which is the value contained in the list.
Combining enumerate() and max() with key (plus a little help from lambda to create a function that returns the second element of a tuple) gives you this solution.
index, value = max(enumerate(list1), key=lambda x: x[1])
I came up with this recently (and am sprinkling it everywhere in my code) after watching Raymond Hettinger's talk on Transforming Code into Beautiful, Idiomatic Python, where he suggests exorcising the for i in xrange(len(list1)): pattern from your code.
Alternatively, without resorting to lambda (Thanks #sweeneyrod!):
from operator import itemgetter
index, value = max(enumerate(list1), key=itemgetter(1))
I believe if you change your for loop to....
for i in range (len(arg)):
if arg[i] > ans:
ans = arg[i]
it should work.
You could try something like this. If the list is empty, then the function will return an error.
m is set to the first element of the list, we then iterate over the list comparing the value at ever step.
def findMax(xs):
m = xs[0]
for x in xs:
if x > m:
m = x
return m
findMax([]) # error
findMax([1]) # 1
findMax([2,1]) # 2
if you wanted to use a for loop and make it more generic, then:
def findGeneric(pred, xs):
m = xs[0]
for x in xs:
if pred(x,m):
m = x
return m
findGeneric(lambda a,b: len(a) > len(b), [[1],[1,1,1,1],[1,1]]) # [1,1,1,1]

For Loop to While Loop using IN for while loops

I am quite new to Python 2.7 so I had a couple of questions regarding using for loops to while loops.
For example: I am writing this definition
def missingDoor(trapdoor,roomwidth,roomheight,step):
safezone = []
hazardflr = givenSteps(roomwidth,step,True)
safetiles = []
for m in hazardflr:
safetiles.append((m,step))
i = 0
while i < len(safetiles):
nextSafe = safetiles[i]
if knownSafe(roomwidth, roomheight, nextSafe[0], nextSafe[1]):
if trapdoor[nextSafe[0]/roomwidth][nextSafe[0]%roomwidth] is "0":
if nextSafe[0] not in safezone:
safezone.append(nextSafe[0])
for e in givenSteps(roomwidth,nextSafe[0],True):
if knownSafe(roomwidth, roomheight, e, nextSafe[0]):
if trapdoor[e/roomwidth][e%roomwidth] is "0" and (e,nextSafe[0]) not in safetiles:
safetiles.append((e,nextSafe[0]))
i += 1
return sorted(safezone)
I am trying to turn all the for loops to a while loops, so this is currently what I have written so far. I actually dont know if we say "While e in " works near the middle of the code. But using the while loop rules, will this code do the same as the for loop one?
safezone = []
hazardflr = givenSteps(roomwidth,step,True)
safetiles = []
m=0
while m < hazardflr:
safetiles.append((m,step))
i = 0
while i < len(safetiles):
nextSafe = safetiles[i]
if knownSafe(roomwidth, roomheight, nextSafe[0], nextSafe[1]):
if trapdoor[nextSafe[0]/roomwidth][nextSafe[0]%roomwidth] is "0":
if nextSafe[0] not in safezone:
safezone.append(nextSafe[0])
e=0
while e in givenSteps(roomwidth,nextSafe[0],True):
if knownSafe(roomwidth, roomheight, e, nextSafe[0]):
if trapdoor[e/roomwidth][e%roomwidth] is "0" and (e,nextSafe[0]) not in safetiles:
safetiles.append((e,nextSafe[0]))
e+=1
i += 1
m+=1
return sorted(safezone)
thanks for any advice or help!
No, your code isn't identical.
While they look similar, for item in list and while item in list will do wildly different things.
for item in list is a syntactic way of saying for every item in the list - do something with is.
while item in list is different - a while loop iterates as long as the condition is true. The condition in this case being item in list. It doesn't update the item each iteration and if you never change what item or list are, it might never terminate. Additionally, if any given item isn't in the list it may terminate prematurely.
If you want to iterate through a list and keep a count, using while is the wrong way to go about it. Use the enumerate() function instead.
enumerate() takes a list, and returns a list of tuples, with each item from the list in order with its index, like so:
for i,m in enumerate(hazardflr):
safetiles.append((m,step))
This small change means you no longer have to track your indices manually.
If you are iterating through every item in a list in Python - use for that's what it is designed to do.
It depends on exactly what givenSteps returns, but in general, no. for x in foo evaluates foo once and then assigns x to be each element of foo in turn. while x in foo: ... x += 1, on the other hand, evaluates foo on every iteration and will end early if foo is not a contiguous sequence. For example, if foo = [0, 1, 2, 5, 6], for will use every value of foo, but while will end after 2, because 3 is not in foo. while will also differ from for if foo contains any non-integral values or values below the starting value.
while aList:
m= hazardflr.pop()
# ...
should be roughly equivelent to your other loop

Index error:list assignment index out of range

I want to:
Take two inputs as integers separated by a space (but in string form).
Club them using A + B.
Convert this A + B to integer using int().
Store this integer value in list C.
My code:
C = list()
for a in range(0, 4):
A, B = input().split()
C[a] = int(A + B)
but it shows:
IndexError: list assignment index out of range
I am unable understand this problem. How is a is going out of the range (it must be starting from 0 ending at 3)?
Why it is showing this error?
Why your error is occurring:
You can only reference an index of a list if it already exists. On the last line of every iteration you are referring to an index that is yet to be created, so for example on the first iteration you are trying to change the index 0, which does not exist as the list is empty at that time. The same occurs for every iteration.
The correct way to add an item to a list is this:
C.append(int(A + B))
Or you could solve a hella lot of lines with an ultra-pythonic list comprehension. This is built on the fact you added to the list in a loop, but this simplifies it as you do not need to assign things explicitly:
C = [sum(int(item) for item in input("Enter two space-separated numbers: ").split()) for i in range(4)]
The above would go in place of all of the code that you posted in your question.
The correct way would be to append the element to your list like this:
C.append(int(A+B))
And don't worry about the indices
Here's a far more pythonic way of writing your code:
c = []
for _ in range(4): # defaults to starting at 0
c.append(sum(int(i) for i in input("Enter two space-separated numbers").split()))
Or a nice little one-liner:
c = [sum(int(i) for i in input("Enter two space-separated numbers").split()) for _ in range(4)]

Categories