Python: Can't change a dictionary field while iterating over it - python-3.x

I have this list:
>>> stud
[19, 11, 6, 26]
If I loop over the 'draws' field, I get the following:
>>> [aluDict[str(s)]['draws'] for s in stud]
[1, 0, 1, 0]
Now I want to add 1 to each of those, so as to obtain (potentially) the following:
>>> [aluDict[str(s)]['draws'] for s in stud]
[2, 1, 2, 1]
In order to do so, I tried this:
>>> [aluDict[str(s)]['draws']+=1 for s in stud]
File "<stdin>", line 1
[aluDict[str(s)]['draws']+=1 for s in stud]
^
SyntaxError: invalid syntax
If I do it individually, I can accomplish that:
>>> aluDict[str(19)]['draws']
2
>>> aluDict[str(19)]['draws']+=1
>>> aluDict[str(19)]['draws']
3
Why is this happening? What am I missing?
Thanks!

If you just want the list [2, 1, 2, 1] and don't want to actually change any of the values stored in aluDict, use +1:
[aluDict[str(s)]['draws']+1 for s in stud]

Related

Numpy: Selecting Rows based on Multiple Conditions on Some of its Elements

I believe this is not a duplicate question, although there are questions that are fairly close to this one on the website. I would like to isolate a row from a numpy list given a set of conditions for some of its elements. Here is an example, consider the array Z:
>>> Z = [[1,0,3,4], [1,1,3,6], [1,2,3,9], [1,3,4,0], [2,1,4,5]]
>>> Z = np.array(Z)
>>> Z
array([[1, 0, 3, 4],
[1, 1, 3, 6],
[1, 2, 3, 9],
[1, 3, 4, 0],
[2, 1, 4, 5]])
and say I would like to isolate the row whose first and second element are both 1. The command that executes that should output the row
np.array([[1, 1, 3, 6]])
However, if I follow this popular question, and make an intuitive extension, such as:
Z[Z[:,0] == 1 & Z[:,1] == 1, :]
I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Is there any quick fix to that? I do not want to iterate over my list. I was wondering if there is a quick "numpy" way for it.
Elegant is np.equal
Z[np.equal(Z[:, [0,1]], 1).all(axis=1)]
Or:
Z[np.equal(Z[:,0], 1) & np.equal(Z[:,1], 1)]
More simple
print (Z[(Z[:,0]==1)&(Z[:,1]==1)])
or
print (Z[(Z[:,0]==1)&(Z[:,1]==1),:])
You got
[[1 1 3 6]]

Python: How to reset the list to original value inside the for loop for every iteration?

I'm trying to pop every values one by one from a list in order to find the min and max sum. While doing that I'm resetting the list to its original value after every iteration, but it doesn't seems to be working...
a=[1,2,3,4,5]
res=[]
for i in range(len(a)):
#print(a)
lst=a
#print(lst)
lst.pop(i)
print(lst)
res.append(sum(lst))
print(min(res))
print(max(res))
[2, 3, 4, 5]
[2, 4, 5]
[2, 4]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-33-42daa1037d37> in <module>
5 lst=a
6 #print(lst)
----> 7 lst.pop(i)
8 print(lst)
9 res.append(sum(lst))
IndexError: pop index out of range
I'm resetting the "lst" to "a" after every iteration, but its not working as expected.
Expected result:
[2, 3, 4, 5]
[1, 3, 4, 5]
[1, 2, 4, 5]
[1, 2, 3, 5]
[1, 2, 3, 4]
10
14
Any help would be appreciated!
The operator "=" doesn't duplicate your list into two different object.
In fact "lst" and "a" both refer to the same object.
Which means if you modify "lst" you will also modify "a" :
>>> a=[1,2,3,4,5]
>>> lst = a
>>> lst.pop(0)
>>> print(a)
[2, 3, 4, 5]
You can change this behavior using the module copy and its function deepcopy. It will duplicate your list and not affect your original one.
import copy
a=[1,2,3,4,5]
res=[]
for i in range(len(a)):
#print(a)
lst= copy.deepcopy(a)
#print(lst)
lst.pop(i)
print(lst)
res.append(sum(lst))
print(min(res))
print(max(res))

I am solving the problem of saving and printing duplicate values ​in lists with Python, but I get the following error: How do I fix this?

# Input:
# - list_data_a: list of numeric or character values
# - list_data_b: list of numeric or character values
# Output:
# - long list of list_data_a and list_data_b is returned
# If the lengths are the same, the value of two list_data_a is returned.
# Examples:
# >>> import gowithflow as gwf
# >>> a = [1, 2, 3, 4, 5, 6]
# >>> b = [1, 2, 3]
# >>> gwf.comparison_list_size (a, b)
# [1, 2, 3, 4, 5, 6]
# >>> b = [1, 2, 3, 5, 7, 8, 9, 10]
# >>> gwf.comparison_list_size (a, b)
# [1, 2, 3, 5, 7, 8, 9, 10]
# '' '
# === Modify codes below =============
# You can write more than one line of code,
# Must be returned by assigning result value to result variable
list_data = [5, 10, 15, 20]
element_value = [5, 10, 58, 88]
for i in range(len(list_data)):
if list_data[i] in element_value:
list_data.remove(list_data[i])
print(len(list_data))
print('-----------')
print(element_value)
if list_data[i] in element_value:
IndexError: list index out of range
use list in a loop, is not it possible to use for i in range (len ()) to iterate over the size of list?
PS. Sorry I could not speak English ...
list_data = [5, 10, 15, 20]
element_value = [5, 10, 58, 88]
for i in list_data:
if i in element_value:
list_data.remove(i)

What is the pythonic way of extracting (& removing) a slice from a list? Or... What is the "inverse" of the slice+=list operator - python

I know how insert a list into a list, "slice+=list" ...
master=[0,1,2,3,7,8,9]
master[:4]+=[4,5,6] # insert 4,5,6
(crudely) The inverse of this operation is removing a slice 4:7 from the list, I tried:
extracted=del master[4:7]
But this gives a syntax error "SyntaxError: invalid syntax".
Likewise the inverse slice operator "-=" doesn't appear to exist.
As a workaround I have used the following:
extracted=master[4:7]; del master[4:7]
This "works" and the "extracted" is the subslice removed from "master", e.g.
print dict(master=master,extracted=extracted)
Output:
{'extracted': [4, 5, 6], 'master': [0, 1, 2, 3, 7, 8, 9]}
Is there a better/pythonic/simpler way ?
In particular I don't like the repeated [4:7] in:
extracted=master[4:7]; del master[4:7]"
Because of potential side-effects: eg
extracted=master[randint(0,3):randint(7,10)]; del master[randint(0,3):randint(7,10)]
i.e. the following reads much better, and would have no "side-effects"...
extracted=del master[randint(0,3):randint(7,10)]
Any hints? Is there a slice "-=" operator I could have used to invert the action of the slice "+=" operator?
Your best bet is to use a slice:
-> s = slice(4, 7)
-> master
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
--> extracted = master[s]
--> extracted
[4, 5, 6]
--> del master[s]
--> master
[0, 1, 2, 3, 7, 8, 9]
It still requires two commands, but you can use a single object to respresent the piece you want.
For me the cleaner option is as follows:
>>> L=[1,2,3,4,5,6] #Define the list
>>> L #Check it
[1, 2, 3, 4, 5, 6]
>>> extract= L[3:6] ; L[3:6]=[] #Assign the slice to 'extract'; delete the slice
>>> L #Items removed from the list
[1, 2, 3]
>>> extract #And assigned to extract
[4, 5, 6]
Cheers!

Python Moving numbers in a list

How can I go about moving numbers in a given list?
For example (if I move 5):
example_list = [5,6,7,10,11,12]
output:
[6,7,5,10,11,12]
or if I move 12 output:
[5,12,6,7,10,11]
Is there a built-in Python function that can allow me to do that?
You can use the built in pop and insert functionality of the list. Here you specify the index of what element you want to pop and the index you where you want to insert it.
example_list = [5,6,7,10,11,12]
example_list.insert(2,example_list.pop(0))
[6, 7, 5, 10, 11, 12]
and for the second example:
example_list.insert(0,example_list.pop(5))
[12, 6, 7, 5, 10, 11]
This can also be done as a two step process.
element = example_list.pop(5)
example_list.insert(0,element)
As an aside, If you don't want to specify the index yourself you can use the index function to find the first index of the value.
element = example_list.pop(example_list.index(12))
example_list.insert(0,element)
Use collections.deque.rotate:
>>> from collections import deque
>>> lis = [5,6,7,10,11,12]
>>> d = deque(lis)
>>> d.rotate(1)
>>> d
deque([12, 5, 6, 7, 10, 11])
>>> d.rotate(-2)
>>> d
deque([6, 7, 10, 11, 12, 5])
Help on deque.rotate:
rotate(...)
Rotate the deque n steps to the right (default n=1). If n is negative,
rotates left.
To move 5 after 7:
>>> lis = [5,6,7,10,11,12]
>>> x = lis.pop(lis.index(5))
>>> lis.insert(lis.index(7)+1 , x)
>>> lis
[6, 7, 5, 10, 11, 12]
Note that list.index returns the index of first matched item, to get indexes of all matched items use enumerate.
You could do this:
def move(a_list, original_index, final_index):
a_list.insert(final_index, a_list.pop(original_index))
return a_list
Example:
>>> move([5,6,7,10,11,12], 0, 2)
[6,7,5,10,11,12]
If you wanted to move the first 5 in the list then you could do this:
>>> my_list = [5,6,7,10,11,12]
>>> move(my_list, my_list.index(5), 2)
[6,7,5,10,11,12]

Resources