Anis Souames
Anis Souames

Reputation: 344

Why is this if condition working partially?

I have a list of dicts, which I would like to delete all dicts where the value of few specific keys is smaller than their counterpart in another dict :

Here's my code :

for d in clean_hosting_dicts:
    if (int(str(d["cores"]) ) < int(self.query["cores"]) ) or ( float(str(d["bandwidth"]).replace(",",".") ) < int(str(self.query["bandwidth"])) ) or ( float(str(d["storage"]).replace(",",".") ) < int(str(self.query["storage"])) ) or (float(str(d["ram"]).replace(",",".") ) < int(str(self.query["ram"])) ):
        del clean_hosting_dicts[clean_hosting_dicts.index(d)]

Where clean_hosting_dicts is my list of dicts and self.query is another dict which has the same key but other values to test against them .

Here's the json for self.query :

{"hosting_type" : "vps","cores": "3", "storage" :"2", "bandwidth" : "1", "ram" : "2", "ip" : "1"}

And here's the json for the list of dicts before this code runs (unfiltered list ) :

[
  {
    "support_score": "4,5",
    "name": "Hostgator Snappy 8000",
    "ip": "2",
    "support": "chat,email,docs,phone,ticket",
    "ram": "8",
    "storage": "240",
    "frequency_rate": 3,
    "cpu": "AMD Opteron 6378",
    "reviews": "3",
    "bandwidth": "3",
    "domains": "1",
    "cores": "4",
    "os": "CentOS 66",
    "price": "39,95",
    "guarantee": "45"
  },
  {
    "support_score": "3,5",
    "name": "Bluehost Standard",
    "ip": "1",
    "support": "email,chat,doc,phone,ticket",
    "ram": "2",
    "storage": "30",
    "frequency_rate": 3,
    "cpu": "AMD Opteron 6378",
    "reviews": "3,2",
    "bandwidth": "1",
    "domains": "1",
    "cores": "2",
    "os": "CentOS 66",
    "price": "19,99",
    "guarantee": "30"
  },
  {
    "support_score": "3,5",
    "name": "Bluehost Enhanced",
    "ip": "2",
    "support": "email,chat,doc,phone,ticket",
    "ram": "4",
    "storage": "60",
    "frequency_rate": 3,
    "cpu": "AMD Opteron 6378",
    "reviews": "3,2",
    "bandwidth": "2",
    "domains": "1",
    "cores": "2",
    "os": "CentOS 66",
    "price": "29,99",
    "guarantee": "30"
  },
  {
    "support_score": "3,5",
    "name": "Bluehost Ultimate",
    "ip": "2",
    "support": "email,chat,doc,phone,ticket",
    "ram": "8",
    "storage": "240",
    "frequency_rate": 3,
    "cpu": "AMD Opteron 6378",
    "reviews": "3,2",
    "bandwidth": "4",
    "domains": "1",
    "cores": "4",
    "os": "CentOS 66",
    "price": "59,99",
    "guarantee": "30"
  },
  {
    "support_score": "4",
    "name": "iPage Business",
    "ip": "2",
    "support": "email,chat,doc,phone,ticket",
    "ram": "4",
    "storage": "90",
    "frequency_rate": 3,
    "cpu": "Unknown",
    "reviews": "3,7",
    "bandwidth": "3",
    "domains": "1",
    "cores": "2",
    "os": "CentOS 64",
    "price": "47,99",
    "guarantee": "30"
  },
  {
    "support_score": "4,5",
    "name": "InMotion vps-1000ha-s",
    "ip": "3",
    "support": "email, phone, skype, ticket,chat",
    "ram": "4",
    "storage": "75",
    "frequency_rate": 3,
    "cpu": "Unknown",
    "reviews": "4,5",
    "bandwidth": "4",
    "domains": "1",
    "cores": 5,
    "os": "CentOS 66",
    "price": "29,99",
    "guarantee": "30"
  },
  {
    "support_score": "4,5",
    "name": "InMotion vps-3000ha-s",
    "ip": "5",
    "support": "email, phone, skype, ticket,chat",
    "ram": "8",
    "storage": "260",
    "frequency_rate": 3,
    "cpu": "Unknown",
    "reviews": "4,5",
    "bandwidth": "6",
    "domains": "1",
    "cores": 5,
    "os": "CentOS 66",
    "price": "74,99",
    "guarantee": "30"
  },
  {
    "support_score": "4",
    "name": "Fatcow Business",
    "ip": "2",
    "support": "email,chat,doc,phone,ticket",
    "ram": "4",
    "storage": "90",
    "frequency_rate": 3,
    "cpu": "Unknown",
    "reviews": "3,8",
    "bandwidth": "3",
    "domains": "1",
    "cores": "2",
    "os": "CentOS 64",
    "price": "47,99",
    "guarantee": "30"
  },
  {
    "support_score": "4",
    "name": "1and1 Cloud L",
    "ip": "1",
    "support": "email,doc,phone,ticket",
    "ram": "2",
    "storage": "80",
    "frequency_rate": 3,
    "cpu": "Intel Xeon",
    "reviews": "3",
    "bandwidth": "0",
    "domains": "1",
    "cores": "2",
    "os": "CentOS 7",
    "price": "14,99",
    "guarantee": "30"
  },
  {
    "support_score": "4,5",
    "name": "Hostgator Snappy 2000",
    "ip": "2",
    "support": "chat,email,docs,phone,ticket",
    "ram": "2",
    "storage": "120",
    "frequency_rate": 3,
    "cpu": "AMD Opteron 6376",
    "reviews": "3",
    "bandwidth": "1,5",
    "domains": "1",
    "cores": "2",
    "os": "CentOS 64",
    "price": "19,95",
    "guarantee": "45"
  }
]

After this code runs it delete all dicts that don't meet requirements, except one "the one whose name is 1&1 Cloud L" , this one has "2" as a value for cores and the query["cores"] is 4 which is bigger than two (I'm converting all this values into numbers )

I don't know why it doesn't get deleted, I couldn't find anything that would help online ir by debugging via pdb .

Upvotes: 4

Views: 107

Answers (2)

Stephen Rauch
Stephen Rauch

Reputation: 49794

A list comprehension can be used to pare down a list based on a conditional:

clean_hosting_dicts = [
    d for d in clean_hosting_dicts
    if not ((int(str(d["cores"])) < int(self.query["cores"])) or (
        float(str(d["bandwidth"]).replace(",", ".")) < int(
            str(self.query["bandwidth"]))) or (
        float(str(d["storage"]).replace(",", ".")) < int(
            str(self.query["storage"]))) or (
        float(str(d["ram"]).replace(",", ".")) < int(str(self.query["ram"]))))
]

In the OP's code, the problem comes when deleting items from a list as it is being iterated on. The above approach can work because a new list is built and then assigned back to the original name.

Note (from the comments) that this will build an entirely new object, so if someone has a reference to the original list, that list will not be updated.

Upvotes: 1

ebeneditos
ebeneditos

Reputation: 2612

The problem is that you are deleting items from the list that you are iterating, so I recommend iterating on a different list, for instance with the expression:

for d in clean_hosting_dicts[:]:
    ...

So you iterate over an equal list, although not the same object, and delete only in the original.

Hope this helped!

Upvotes: 3

Related Questions