6

In python 3.6 dict is ordered so now we can rely on items having certain locations. I realize that's not entirely accurate but I can't remember the exact details. Right now the only location I've been worried about is the zeroeth location. So suppose I have the following dictionary:

dict1 = {'a':1,'b':2}

And I want to insert key {'c':3} into the zeroeth location. I can do that in three lines of code, but I bet there is a shorter way to do it:

temp_dict = {}
temp_dict.update({'c':3})
dict1 = {**temp_dict,**dict1}
dimo414
  • 47,227
  • 18
  • 148
  • 244
bobsmith76
  • 160
  • 1
  • 9
  • 26
  • FYI I rephrased your question to be more practical - the number of lines or characters isn't really important, but being able to express something in a single statement or expression often is (and by the sound of it is what you're actually looking for). – dimo414 Jul 18 '17 at 04:45

3 Answers3

9

enter image description here

One line:

dict1 = {k: v for k, v in ([('c', 3)] + list(dict1.items()))}

That was fun. I didn't even have 3.6 installed yet.

Because I found this task so amusing, here's a one line function to insert an item into any position in the dict:

insert = lambda _dict, obj, pos: {k: v for k, v in (list(_dict.items())[:pos] +
                                                    list(obj.items()) +
                                                    list(_dict.items())[pos:])}
martineau
  • 119,623
  • 25
  • 170
  • 301
Cory Madden
  • 5,026
  • 24
  • 37
  • pretty amazing solution – bobsmith76 Jul 18 '17 at 04:41
  • Haha, thanks. I love doing stuff like that. Plus I got to learn something new. – Cory Madden Jul 18 '17 at 04:48
  • what if you wanted to insert the item into position 1 in a dict? – bobsmith76 Jul 18 '17 at 04:52
  • 1
    `dict1 = {k: v for k, v in (list(dict1.items())[:1] + [('c', 3)] + list(dict1.items())[1:])}` :) – Cory Madden Jul 18 '17 at 04:54
  • 3
    You didn't ask for it, but here's a one line function to do it for any position! `z = lambda x: {k: v for k, v in (list(dict1.items())[:x] + [('c', 3)] + list(dict1.items())[x:])}` – Cory Madden Jul 18 '17 at 04:58
  • I don't know why I find this so amusing. I should really go to bed. OK, but last one. I updated my answer with a one line function to insert any dict into any position in any dict. – Cory Madden Jul 18 '17 at 05:04
  • actually, I didn't test this when you wrote it. I just assumed it would work. I'm only just now testing it out. It turns out that I really don't know what to do with lambda. After I run the code z is simply a lambda in my IDE editor and I can't figure out how to use it. I tried revising it as follows z = {k: v for k, v in (list(dict1.items())[:1] + [('c', 3)] + list(dict1.items())[1:])} but that just puts {c: 3} at the end of the dict – bobsmith76 Jul 22 '17 at 03:31
  • 1
    You just call it as a regular function. `lambda` is just a way of defining it on one line. They're called "anonymous functions". Usage would be `insert(my_dict, {'a': 1}, 2)`. You probably shouldn't use the `z` function from my comment as the one in my actual answer which I've updated is better. – Cory Madden Jul 22 '17 at 03:33
  • thanks for the speedy reply but it's still the case that the item to be inserted is being put at the end of the dict, no matter what the position is. See screen shot https://i.imgur.com/AzQeE46.png – bobsmith76 Jul 22 '17 at 03:47
  • I see that, and it works for me. The section right after that line of code in the debugger shows that it's in the correct order, though. It also shows it as being in the correct position at the top of the little dropdown showing the items. I can only assume the debugger shows it based on the memory address, but I'm just guessing. – Cory Madden Jul 22 '17 at 03:50
  • Thanks that did it. Sorry for not knowing being very good with lambda but I guess that's part of the learning process. – bobsmith76 Jul 22 '17 at 03:59
  • No worries. We all start somewhere. – Cory Madden Jul 22 '17 at 04:15
4

Here you go.

dict1 = {'c':3, **dict1}
Worthy7
  • 1,455
  • 15
  • 28
  • 1
    You should just be able to write: `dict1 = {'c':3, **dict1}` you don't need the extra dictionary creation. – cdlane Jul 22 '17 at 04:02
1

In Python 3.6+, you could define your own dict subclass that has an insert() method (since dicts started preserving insertion order at that point). With this approach it the number of lines of code isn't very significant because it's merely "implementation detail" of the new class:

class MyDict(dict):
    def insert(self, pos, new_entry):
        items = list(self.items())  # Convert current contents into a list.
        items.insert(pos, *tuple(new_entry.items()))  # Insert new entry into that list.
        self.clear()
        self.update(type(self)(items))


if __name__ == '__main__':
    dict1 = MyDict({'a': 1,'b': 2})
    dict1.insert(0, {'c': 3})
    print(dict1)  # -> {'c': 3, 'a': 1, 'b': 2}

Instances of the subclass could be used anywhere a regular dictionary object could be.

martineau
  • 119,623
  • 25
  • 170
  • 301