3

I would like to know how I can loop over a Python dictionary without first and last element. My keys doesn't start at 1 so I can't use len(capitals)

>>> capitals = {'15':'Paris', '16':'New York', '17':'Berlin', '18':'Brasilia', '19':'Moscou'}
>>> for city in capitals:
>>>     print(city)
Paris
New York
Berlin
Brasilia
Moscou

I would like this result:

New York
Berlin
Brasilia

My keys doesn't start at 1 so I can't use len(capitals)

Andy G
  • 19,232
  • 5
  • 47
  • 69
Tim C.
  • 167
  • 1
  • 1
  • 8
  • 2
    Dictionaries arent ordered. – RoadRunner Dec 28 '17 at 13:46
  • 2
    A Python dictionary isn't ordered, the first and last items should not be relied upon. To achieve what you want you would have to explicitly skip items with keys '15' and '19', which *you consider* the first and last. If the order is important then don't use a dictionary. – Andy G Dec 28 '17 at 13:46
  • Possible duplicate of [Skip first entry in for loop in python?](https://stackoverflow.com/questions/10079216/skip-first-entry-in-for-loop-in-python) – mehrdadep Dec 28 '17 at 13:52
  • Note that, in Python 3.7, dictionaries [*will* be guaranteed](https://mail.python.org/pipermail/python-dev/2017-December/151283.html) to retain the original insertion order. – chepner Dec 28 '17 at 14:00

7 Answers7

5

Try this, by converting dictionary to list, then print list

c=[city for key,city in capitals.items()]
c[1:-1]

Output

['New York', 'Berlin', 'Brasilia']
Artier
  • 1,648
  • 2
  • 8
  • 22
3

Dictionaries are ordered in Python 3.6+

You could get the cities except the first and the last with list(capitals.values())[1:-1].

capitals = {'15':'Paris', '16':'New York', '17':'Berlin', '18':'Brasilia', '19':'Moscou'}

for city in list(capitals.values())[1:-1]:
    print(city)

New York
Berlin
Brasilia
>>> 

On Fri, Dec 15, 2017, Guido van Rossum announced on the mailing list: "Dict keeps insertion order" is the ruling.

srikavineehari
  • 2,502
  • 1
  • 11
  • 21
2

Since dicts are inherently unordered, you would have to order its items first. Given your example data, you want to skip the first and last by key:

for k in sorted(capitals)[1:-1]:
    print(capitals[k])
user2390182
  • 72,016
  • 6
  • 67
  • 89
2

You could put the data first into a list of tuples with list(capitals.items()), which is an ordered collection:

[('15','Paris'), ('16','New York'), ('17', 'Berlin'), ('18', 'Brasilia'), ('19', 'Moscou')]

Then convert it back to a dictionary with the first and last items removed:

capitals = dict(capitals[1:-1])

Which gives a new dictionary:

{'16': 'New York', '17': 'Berlin', '18': 'Brasilia'}

Then you can loop over these keys in your updated dictionary:

for city in capitals:
    print(capitals[city])

and get the cities you want:

New York
Berlin
Brasilia
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • 2
    This should be the accepted answer, as it deals with unordered nature of `dict` and a nice explanation as well – Sohaib Farooqi Dec 28 '17 at 14:15
  • 1
    @GarbageCollector Cheers, I thought it would be a bit easier for the OP to understand if I cover the issues step by step. – RoadRunner Dec 28 '17 at 14:21
  • @StefanPochmann Funny thing is, another answer also said the same thing, but you didn't comment on that. Python 3.6 doesn't have guaranteed ordered dictionaries currently, its still in the process. Either way, I removed that comment. – RoadRunner Dec 28 '17 at 14:34
  • 1
    Well I didn't feel like asking two people about it, and yours was the higher-voted one (with one vote from me for the round-trip idea :-) – Stefan Pochmann Dec 28 '17 at 14:46
  • Cheers mate, I was just curious is all. I hope I didn't sound rude. I should use "*dictionaries are inherently unordered"* with caution, since its not technically true anymore. Looking forward to the guaranteed ordered dicts in Python 3.7. – RoadRunner Dec 28 '17 at 14:51
2

I have to disagree with previous answer and also with Guido's comment saying that "Dict keep insertion order". Dict doesn't keep insertion order all the time. I just tried (on a pyspark interpretor though, but still) and the order is changed. So please look carefully at your environement and do a quick test before running such a code. To me, there is just no way to do that with 100% confidence in Python, unless you explicitly know the key to remove, and if so you can use a dict comprehension:

    myDict = {key:val for key, val in myDict.items() if key != '15'}
N.dP
  • 41
  • 3
1

You can sort dict and then just fetch all values except first and last :

capitals = {'15':'Paris', '16':'New York', '17':'Berlin', '18':'Brasilia', '19':'Moscou'}

for i in sorted(capitals)[:-1][1:]:
    print(capitals[i])

output:

New York
Berlin
Brasilia

In one line:

print([capitals[i] for i in sorted(capitals)[:-1][1:]])
0

As mentioned in the comments. A dictionary is not setup to store data in order, a list would be better for that. Such as a 2d list like [[15,'Paris'],[ [16,'New York'],....]

Below is the code that will get all of the keys (numbers) from the dictionary and put them in the list keys. Then I pop the first (0) element of the list and then use for loop to pull each city with the keys left in the list.

capitals={'15':'Paris', '16':'New York', '17':'Berlin', '18':'Brasilia', '19':'Moscou'}
keys=list(capitals.keys()) #get list of keys from dictionary
keys.pop(0)  #Remove first in list of keys
for key in keys:
    print capitals[key]
Zack Tarr
  • 851
  • 1
  • 8
  • 28
  • Written for 2.7 but I will look at updating the code for both. – Zack Tarr Dec 28 '17 at 14:02
  • Modify you answer so that it grab all keys like `list(capitals.keys())` . It will be compatible with both 2.7 and 3.x – Sohaib Farooqi Dec 28 '17 at 14:20
  • Does capitals.keys() not return a list in 3.x? It looks like the `pop` function is supported in 3.x as well. I havent had a chance to install python 3 so havent tested. – Zack Tarr Dec 28 '17 at 14:28
  • 1
    @ZackTarr `keys` in Python 3.x does not return a list - it returns a [view object](https://docs.python.org/3.3/library/stdtypes.html#dict-views) containing the keys of the dictionary – Wondercricket Dec 28 '17 at 14:47