1

I'm facing a problem that I don't really understand. Please take a look at the given code, where the two relevant variables have the following form:

jsd = {"data": {"User": .....}}
lists = [{"genre": "XY", "meanScore": Float},..., {"genre": "XY", "meanScore": Float}]

The code is:

jsd = json.loads(r.text)  
lists = jsd["data"]["User"]["stats"]["favouredGenresOverview"]
for k, entry in enumerate(lists):
    if entry["meanScore"] == None:
        del(lists[k])

The goal is to remove all the dict's in lists where the key meanScore is equal to None. The problem is that for some reason the loop only runs over half of lists... I think I've read somewhere on the site that when trying to remove something from a dict one should use pop, but I honestly wasn't able to figure out how to that or if it even was relevant to my question (As far as I understand I'm removing list elements).

Can someone maybe help?

Sito
  • 494
  • 10
  • 29
  • 1
    Don't delete items from a list while iterating; plenty of duplicates for the strange behaviour but I think that one best illustrates the skipping of elements. Build a new list of things you want to _keep_ rather than delete elements. – roganjosh Dec 19 '18 at 22:17
  • 1
    don't modify (the shape of) what you're iterating through! – Paritosh Singh Dec 19 '18 at 22:18
  • 1
    @ParitoshSingh don't modify the _length_ of what you are iterating through. Maybe I have a list of integers and I want to multiply them all by 2; I wouldn't have this issue. – roganjosh Dec 19 '18 at 22:20
  • Touche. Not quite as catchy though. :P – Paritosh Singh Dec 19 '18 at 22:20
  • Instead of removing unwanted items from the original list, add wanted items to a new list. As others have said, don't iterate and remove from a collection at the same time, if you do so you desserve all kinds of nasty things, and you're getting them. If you need na explanation of why and what is happening, let me know. – Pedro Rodrigues Dec 19 '18 at 22:22
  • 1
    @PedroRodrigues that is already covered fully in the duplicate I have flagged – roganjosh Dec 19 '18 at 22:25
  • @roganjosh Yep, stackoverflow was outdated on my side. Thumbs up – Pedro Rodrigues Dec 20 '18 at 09:23

2 Answers2

2

A more pythonic approach to these type of problems is to think of what you want to "keep" instead.

jsd = json.loads(r.text)  
lists = jsd["data"]["User"]["stats"]["favouredGenresOverview"]

output_list = [entry for entry in lists if entry["meanScore"] is not None]

You can get fancier with a generator and slicing if you want to do it inplace.

lists[:] = (entry for entry in lists if entry["meanScore"] is not None)
Paritosh Singh
  • 6,034
  • 2
  • 14
  • 33
0
lists = [{"genre": "XY", "meanScore": 'Float'}, {"genre": "XY", "meanScore": None}]
[d for d in lists if d['meanScore'] is not None]

This will give the following output

[{'meanScore': None, 'genre': 'XY'}]
Remy J
  • 709
  • 1
  • 7
  • 18