Alternative to deepcopy in python - python

In a project we have to do for school, we got an assignment to write an implementation for the floyd-warshall algorithm.
One of the restrictions was, that we could not use import statements.
I had not read this and write my algorithm, using deepcopy. Now I am searching for a way to make my own sort of "copy" function.
The thing I want to copy is a dictionary of 2 dictionaries
{"a": {...}, "b": {...}}
Is this possible? thank you very much in advance

You can use a dict comprehension with copy method of dictionary :
d={"a": {...}, "b": {...}}
new={i:j.copy() for i,j in d.items()}
Demo :
>>> d ={1: {1: 5}, 2: {2: 2}, 3: {3: 9}}
>>> l ={i:j.copy() for i,j in d.items()}
>>> l[1][1]=0
>>> l
{1: {1: 0}, 2: {2: 2}, 3: {3: 9}}
>>> d
{1: {1: 5}, 2: {2: 2}, 3: {3: 9}}

Related

Sort dictionary with attribute value

I have a list dictionary like this: {1: {'a': 5, 'score': 3}, 2: {'a': 6, 'score': 1}, 3: {'a': 7, 'score': 2}} and want to sort it using its score attribute.
Intended output: {2: {'a': 6, 'score': 1}, 3: {'a': 7, 'score': 2}, 1: {'a': 5, 'score': 3}}
I have trying to use the built-in function to sort the list but its not giving desired output
updatedList = sorted(b, key=lambda k: k['score'])
Any hints how I can get the desired output?
Your data structure is a nested dictionary, not a list.
To sort the dictionary, you can modify your key function to this:
>>> d = {1: {'a': 5, 'score': 3}, 2: {'a': 6, 'score': 1}, 3: {'a': 7, 'score': 2}}
>>> dict(sorted(d.items(), key=lambda x: x[1]['score']))
{2: {'a': 6, 'score': 1}, 3: {'a': 7, 'score': 2}, 1: {'a': 5, 'score': 3}}
Which converts the original dictionary to dict.items, then uses the score key from the dictionary in the (key, value) tuple. Then after sorting with sorted(), we can convert back to a dictionary with dict().
This works in Python 3.6+ since dictionaries are ordered. If you are using a lower python version, you can maintain dictionary insertion order with collections.OrderedDict instead.
For sorting a Nested Dictionary use the key argument for sorted(). It lets you specify a function that, given the actual item being sorted, returns a value that should be sorted by.
N_Dictionary = {1: {'a': 5, 'score': 3}, 2: {'a': 6, 'score': 1}, 3: {'a': 7, 'score': 2}}
s_values = sorted(N_Dictionary.items(), key = lambda x: x[1]["score"] )
s_values

How to add an existing dictionary as a nested dictionary to an already existing dictionary in python?

In python3, I have 2 dictionaries, dict1 and dict2 that are both populated with key/value pairs. I want to create a new dictionary dict3 and add both dict1 and dict2 as nested dictionaries to it. I cant BELIEVE how much time Ive wasted trying to google a solution. I find tutorial after tutorial about how to create nested dictionaries from scratch but nothing about adding an existing dictionary nested to another dictionary.
IIUC:
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3=dict(list(dict1.items())+[('dict2', dict2)])
print(dict3)
Output:
{1: 2, 3: 4, 'dict2': {5: 6, 7: 8}}
Or if you want to add the two dictionary:
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3=dict([('dict1', dict1)]+[('dict2', dict2)])
print(dict3)
#Output:
#{'dict1': {1: 2, 3: 4}, 'dict2': {5: 6, 7: 8}}
Another ways:
#first scenario
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3={**dict1}
dict3.update({'dict2':dict2})
print(dict3)
#Output:
#{1: 2, 3: 4, 'dict2': {5: 6, 7: 8}}
#second scenario
dict1={1:2,3:4}
dict2={5:6,7:8}
dict3={}
dict3.update({'dict1':dict1,'dict2':dict2})
print(dict3)
#Output:
#{'dict1': {1: 2, 3: 4}, 'dict2': {5: 6, 7: 8}}

Why can't I write this nested for loop as a list comprehension? [duplicate]

I'm trying to unpack a complex dictionary and I'm getting a NameError in a list comprehension expression using multiple loops:
a={
1: [{'n': 1}, {'n': 2}],
2: [{'n': 3}, {'n': 4}],
3: [{'n': 5}],
}
good = [1,2]
print [r['n'] for r in a[g] for g in good]
# NameError: name 'g' is not defined
You have the order of your loops mixed up; they are considered nested from left to right, so for r in a[g] is the outer loop and executed first. Swap out the loops:
print [r['n'] for g in good for r in a[g]]
Now g is defined for the next loop, for r in a[g], and the expression no longer raises an exception:
>>> a={
... 1: [{'n': 1}, {'n': 2}],
... 2: [{'n': 3}, {'n': 4}],
... 3: [{'n': 5}],
... }
>>> good = [1,2]
>>> [r['n'] for g in good for r in a[g]]
[1, 2, 3, 4]

Reading from file into dictionaries, and strange eval() behaviour

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.

Dictionary comprehension with conditional

So I'm wondering if anyone can help me out with this issue I'm having.
Lets assume I have a dictionary:
d = {1: {2: 3}, 4: 5}
I want to create a dictionary of any contained dictionaries:
wanted_result = {2: 3}
what I am trying is this:
e = {inner_key: d[key][inner_key] for key in d.keys() for inner_key in d[key].keys() if isinstance(d[key], dict)}
However this is causing me to get an error saying that ints don't have keys, which I know, but I thought my conditional would exclude say 4 from my example from being included in the comprehension.
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = {k: v for elem in d.values() if type(elem) is dict for k, v in elem.items()}
>> {2: 3, 7: 8}
In this case, I would recommend you a for-loop and the update method:
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
inner_dicts = {}
for val in d.values():
if type(val) is dict:
inner_dicts.update(val)
print inner_dicts
# {2: 3, 7: 8}
My first idea was something like this:
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
generator = (x.items() for x in d.itervalues() if type(x) == dict)
s = dict(sum( generator, list() ))
# s = {2: 3, 7: 8}
But, in order to avoid letting sum() construct a large temporary list of all the items() you may use itertools.chain and iteritems() instead:
# chain "concatenates" iterables
from itertools import chain
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = dict(chain( *(x.iteritems() for x in d.itervalues() if type(x) == dict) ))
# s = {2: 3, 7: 8}
You should be aware of edge cases. Especially if identical keys are in the part-dictionaries these will necessarily collapse somehow.
If you also want to support subclasses of dict to be collected from your d.values(), you may indeed want to use isinstance instead of type. See this question for details.
The following list comprehension will return each value that is a dict:
>>> d = {1: {2: 3}, 4: 5}
>>> [d[i] for i in d.keys() if isinstance(d[i],dict)]
[{2: 3}]
d = {1: {2: 3}, 4: 5,'j':{7:8}}
e={y:d[x][y] for x in d if isinstance(d[x],dict) for y in d[x]}
print(e)
{2: 3, 7: 8}
Other way using lambda
(lambda x: {k:v for x in d.values() if type(x) == dict for k,v in x.items()})(d)

Categories