When I try the following list creation, I see that each element refers to a different object.
>>> a = [1] * 7
>>> a[0] = 2
>>> a
Out[17]: [2, 1, 1, 1, 1, 1, 1]
However, when I try the following list creation with dictionaries, I see that each element refers to the same object.
a = [{1:10, 2:20}] * 7
a[0][1] = 30
a
Out[20]:
[{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20},
{1: 30, 2: 20}]
How can I create this second list as easy as possible, but with the elements copies instead of references?
>>> a = [{1:10, 2:20} for _ in range(7)]
>>> a[0][1] = 30
>>> a
[{1: 30, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
Actually when you create a list with multiplication python will creating a list with repeated items with same memory address :
>>> a=[1]*7
>>> id(a[0])
40968536
>>> id(a[1])
40968536
>>> a = [{1:10, 2:20}]*7
>>> id(a[0])
140379402804592
>>> id(a[1])
140379402804592
But when you want to change an immutable object like (numbers,tuple,string,...) python will change the reference not the object!
And when you change a mutable object python will change the object itself,so all the entries will change.
So as a more efficient way in python 2 you can use xrange (xrange return a generator instead a list) (in 3 range ) within a list comprehension to create your list :
>>> a = [{1:10, 2:20} for _ in xrange(7)]
>>> a
[{1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
>>> a[0][1]=0
>>> a
[{1: 0, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
>>> id(a[0])
140379402734400
>>> id(a[1])
140379402809424
Related
Suppose I have a list
[{0: [0, 1, 2, 3], 1: [4]}, {2: [5, 6, 7, 8], 3: [9]}, {4: [10, 11, 12]}]
and another dictionary
servicesdict = { 0 : {'cost' : 30},
1 : {'cost' : 50},
2 : {'cost' : 70},
3 : {'cost' : 20},
4 : {'cost' : 20},
5 : {'cost' : 10},
6 : {'cost' : 20},
7 : {'cost' : 50},
8 : {'cost' : 70},
9 : {'cost' : 20},
10 : {'cost' : 20},
11 : {'cost' : 20},
12 : {'cost' : 40},
}
I wrote
{k: [min(v, key = lambda x:servicesdict[x]['cost'])]for item in newlist for k, v in item.items()}to get the minimum cost of the list element in each subdictionary of the list
This produces the minimum list element not just the cost
{0: [0], 1: [4], 2: [5], 3: [9], 4: [10]}
How do I get the corresponding cost as well? That is, the output should be
{0: [0, 20], 1: [4, 20], 2: [5, 10], 3: [9, 20], 4: [10, 20]}
servicesdict = {
0: {'cost': 30},
1: {'cost': 50},
2: {'cost': 70},
3: {'cost': 20},
4: {'cost': 20},
5: {'cost': 10},
6: {'cost': 20},
7: {'cost': 50},
8: {'cost': 70},
9: {'cost': 20},
10: {'cost': 20},
11: {'cost': 20},
12: {'cost': 40},
}
newlist = [{0: [0, 1, 2, 3], 1: [4]}, {2: [5, 6, 7, 8], 3: [9]}, {4: [10, 11, 12]}]
mins = {
k: min([[servicesdict[x]['cost'], x] for x in sublist])
for dct in newlist
for k, sublist in dct.items()
}
print(mins)
# {0: [20, 3], 1: [20, 4], 2: [10, 5], 3: [20, 9], 4: [20, 10]}
Basically convert each sublist to a list of [cost, id] pairs and take the min of that. The default comparison for lists will compare the cost first. If you make [id, cost] pairs instead then you need to provide a key to sort by cost.
Perhaps the simplest approach here is to use the obtained list:
d = {k: [min(v, key = lambda x:servicesdict[x]['cost'])] for item in newlist
for k, v in item.items()}
And add the corresponding cost with the bellow dictionary comprehension:
{k: [*v, servicesdict[v[0]]['cost']] for k,v in d.items()}
# {0: [3, 20], 1: [4, 20], 2: [5, 10], 3: [9, 20], 4: [10, 20]}
You can apply min twice:
d = [{0: [0, 1, 2, 3], 1: [4]}, {2: [5, 6, 7, 8], 3: [9]}, {4: [10, 11, 12]}]
servicesdict = {0: {'cost': 30}, 1: {'cost': 50}, 2: {'cost': 70}, 3: {'cost': 20}, 4: {'cost': 20}, 5: {'cost': 10}, 6: {'cost': 20}, 7: {'cost': 50}, 8: {'cost': 70}, 9: {'cost': 20}, 10: {'cost': 20}, 11: {'cost': 20}, 12: {'cost': 40}}
result = {a:[min(b), min(servicesdict[i]['cost'] for i in b)] for c in d for a, b in c.items()}
Output:
{0: [0, 20], 1: [4, 20], 2: [5, 10], 3: [9, 20], 4: [10, 20]}
Edit: if you want the first element in each list to be the key of the minimum value in servicesdict, then min with key` can be applied:
result = {a:[min(b, key=lambda x:servicesdict[x]['cost']), min(servicesdict[i]['cost'] for i in b)] for c in d for a, b in c.items()}
Output:
{0: [3, 20], 1: [4, 20], 2: [5, 10], 3: [9, 20], 4: [10, 20]}
I have a list which is like this:
[{0: 26},
{0: 36},
{1: 1},
{0: 215},
{1: 63},
{0: 215}]
How can I extract a list of keys from it?
[0, 0, 1, 0, 1, 0]
Use dict.keys() to get keys out of a dictionary and use it in a list-comprehension like below:
lst = [{0: 26},
{0: 36},
{1: 1},
{0: 215},
{1: 63},
{0: 215}]
print([y for x in lst for y in x.keys()])
# [0, 0, 1, 0, 1, 0]
Or, this should be further simplified as:
print([y for x in lst for y in x])
Because, when you simply iterate through dictionary like for y in x, you are actually iterating through keys of the dictionary.
Use dict.keys to extract the keys of each of the dict, convert to a list, and then extract the first element
>>> lst = [{0: 26}, {0: 36}, {1: 1}, {0: 215}, {1: 63}, {0: 215}]
>>> [list(d.keys())[0] for d in lst]
[0, 0, 1, 0, 1, 0]
Alternatively, you can use list comprehension as below
>>> [k for d in lst for k in d.keys()]
[0, 0, 1, 0, 1, 0]
I suggest you to simply iterate over the list of dictionaries, and to iterate over the keys of each dictionary, using list comprehension as follows:
myList = [{0: 26}, {0: 36}, {1: 1}, {0: 215}, {1: 63}, {0: 215}]
newList = [k for d in myList for k in d]
print(newList) # [0, 0, 1, 0, 1, 0]
Those are the keys so you would use the dict.keys() method:
L = [{0: 26},
{0: 36},
{1: 1},
{0: 215},
{1: 63},
{0: 215}]
L2 = [list(d.keys())[0] for d in L]
use keys() function of dict().
a = [{0: 26}, {0: 36}, {1: 1}, {0: 215}, {1: 63}, {0: 215}]
keys = list(a.keys()[0])
vaues = (a.values()[0])
Cheers!
you can do it this way :
list = [list(d.keys())[0] for d in originalList] # originalList is the first list you posted
Here's the output : [0, 0, 1, 0, 1, 0]
You can use dict.keys and itertools.chain to build a list of all keys:
from itertools import chain
w = [{0: 26},
{0: 36},
{1: 1},
{0: 215},
{1: 63},
{0: 215}]
keys = list(chain.from_iterable(map(dict.keys, w)))
OR try the below code, using map:
lod=[{0: 26},
{0: 36},
{1: 1},
{0: 215},
{1: 63},
{0: 215}]
print(list(map(lambda x: list(x.keys())[0])))
I have this kind of dictionary in python:
x = {'test': {1: 2, 2: 4, 3: 5},
'this': {1: 2, 2: 3, 7: 6},
'is': {1: 2},
'something': {90: 2,92:3}}
I want to modify all of the value in the key by whatever value I want. Let's say 100, the methods I tried are below:
counter = 1
print(x)
for key,anotherKey in x.items():
while counter not in x[key]:
counter+=1
while counter in x[key]:
x[key][counter] = 100
counter+=1
counter =0
Which got the result below:
{'test': {1: 100, 2: 100, 3: 100},
'this': {1: 100, 2: 100, 7: 6},
'is': {1: 100},
'something': {90: 100,92: 3}}
I know why this is happening it's because the loop doesn't consider if the differences is more than 1 which in this case in 'this' : where the differences from 2 to 7 is more than 1. However I don't know how to solve this.
You can iterate via a nested for loop:
x = {'test': {1: 2, 2: 4, 3: 5},
'this': {1: 2, 2: 3, 7: 6},
'is': {1: 2},
'something': {90: 2,92:3}}
for a in x:
for b in x[a]:
x[a][b] = 100
print(x)
{'is': {1: 100},
'something': {90: 100, 92: 100},
'test': {1: 100, 2: 100, 3: 100},
'this': {1: 100, 2: 100, 7: 100}}
Or for a new dictionary you can use a dictionary comprehension:
res = {a: {b: 100 for b in x[a]} for a in x}
You can use dictionary comprehension in this way:
{a: {b:100 for b in d} for (a,d) in x.items()}
Creating dictionaries from file using eval(), or ast.literal_eval() (as suggested by others) yields strange results, and I'm not sure why.
My file, file.txt contains this:
{0 : {1: 6, 1:8}, 1 : {1:11}, 2 : {3: 9}, 3 : {},4 : {5:3},5 : {2: 7, 3:4}}
I read it into a dictionary and print the contents out as such
graph1 = {}
graph1 = ast.literal_eval(open("file.txt").read())
and I get this thing, where the {1:6} is missing.
{0: {1: 8}, 1: {1: 11}, 2: {3: 9}, 3: {}, 4: {5: 3}, 5: {2: 7, 3: 4}}
I change the contents of 'file.txt' to this:
{0: {2: 7, 3: 4}, 1: {1: 11}, 2: {3: 9}, 3: {}, 4: {5: 3}, 5: {2: 7, 3: 4}}
And then the correct contents display!
Then I change the contents of file.txt to this, where I rewrite 1:6 as 2:6
{0 : {2: 6, 1:8}, 1 : {1:11}, 2 : {3: 9}, 3 : {},4 : {5:3},5 : {2: 7, 3:4}}
And this is the output, where {2:6} and {1:8} switch places!
{0: {1: 8, 2: 6}, 1: {1: 11}, 2: {3: 9}, 3: {}, 4: {5: 3}, 5: {2: 7, 3: 4}}
All I want to do is correctly read the contents of a file into my dictionary. What is going wrong?
Dictionaries can not have duplicate key. In case same key is provided to the dict object, former value is overridden by the later value.
For example:
>>> d = {'a': 'x', 'b': 'y', 'c': 'z', 'a': 'w'}
>>> d
{'a': 'w', 'c': 'z', 'b': 'y'} # ('a': 'x') is overridden by ('a': 'w')
The reason of missing 1:6 is because of that you have 1:8 in your dictionary too, and since python use hash table for implementing the dictionaries, they don't preserve duplicate keys (because they have same hash value) and the reason of changing the order is that dictionaries don't have a specific order because of the way they are implemented.
in the code here
How do I force static methods to use local not global variables in Python?
i have a variable that is being passed between methods besides the one in the question. the variable is current_line
def line_tocsv(csv_dict={}, line={}, current_line=0):
csv_line, current_line = LineHandler.create_csv(current_line, kline)
if current_line in csv_dict:
csv_dict[current_line].update(csv_line)
else:
csv_dict[current_line] = csv_line
return csv_dict
when this code is run, it produced an output simmilar to this
>>> a={0:{"aa":1,"bb":"wasd"},1:{"aa":1,"bb":"wasd"}}
>>> a
{0: {'aa': 1, 'bb': 'wasd'}, 1: {'aa': 1, 'bb': 'wasd'}}
>>> a[1].update({"cc":"foo"})
>>> a
{0: {'aa': 1, 'cc': 'foo' 'bb': 'wasd'}, 1: {'aa': 1, 'cc': 'foo', 'bb': 'wasd'}}
how do i make it so that the csv_line dict is only entered into ONE sub dict?!
changing the variable names does not work and i suspect it is because only the references are passed between functions, but i dont know enough python to know where those references actually go and what their order of ops etc is
First, don't use mutable default arguments
def line_tocsv(csv_dict=None, ....):
if not csv_dict:
csv_dict = {}
....
Next, use copy of dict, not pointer:
csv_dict[current_line] = csv_line.copy()
EDIT:
Try to do this:
>>> a
{1: 2, 3: 4}
>>> b = {1:a,2:a}
>>> b
{1: {1: 2, 3: 4}, 2: {1: 2, 3: 4}}
>>> b[1][7] = 8
>>> b
{1: {1: 2, 3: 4, 7: 8}, 2: {1: 2, 3: 4, 7: 8}}
If you want to use value of dict instead of pointer:
>>> a
{1: 2, 3: 4}
>>> b = {1:a.copy(),2:a.copy()}
>>> b
{1: {1: 2, 3: 4}, 2: {1: 2, 3: 4}}
>>> b[1][7] = 8
>>> b
{1: {1: 2, 3: 4, 7: 8}, 2: {1: 2, 3: 4}}