0

First off i am certain that such a basic thing has been asked before, but i could not find a post about it.

I have this piece of example data:

'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'], 
'192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'], 
'192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6'], 
'192.168.244.230': ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']

And i want to print out every line (each line is one dictionary key-value pair) that has a list-value whose list contains any amount of items that is not 0 (in this case, every line except the 4th)

I just cant seem to figure out this seemingly simple thing - what i tried before was those two things:

for i in d.keys():
    if "0" not in d[i]:
        print(i, d[i])

This one shows only lists that do not contain 0 AT ALL - so the third line would not be shown, even though it contains non-0 values

for i in d.keys():
    for j in d[i]:
        if j is not "0":
            print(i, d[i])

This one DOES show me what i want, but as you can tell, it prints every result way too often - one print for every list value that is not 0.

Flying Thunder
  • 890
  • 2
  • 11
  • 37

7 Answers7

2

Use a dictionary-comprehension:

d = {'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'],
     '192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'],
     '192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6'],
     '192.168.244.230': ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']}

result = {k: v for k, v in d.items() if not all(x == '0' for x in v)}

# {'192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'],
#  '192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'],
#  '192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6']}

The above code generates a new dictionary which omits all items where values are all zeros.

Now that you have a dictionary, you can easily do an iteration like so:

for k, v in result.items():
    print(k, v)
Austin
  • 25,759
  • 4
  • 25
  • 48
2

You can simply iterate over like

def all_zero(arr):
    for i in arr:
        if i != 0:
            return False
    else:
        return True

You can call it on all the lists one by one.

Mark
  • 5,994
  • 5
  • 42
  • 55
1
for i in d.keys():
    all_zero = True
    for j in d[i]:
        if j is not "0":
            all_zero = False
            break
    if not all_zero:
        print(i, d[i])

This may work for almost every language :)

JOHNKYON
  • 83
  • 1
  • 7
1

Your bug is basically just a missing break:

for i in d.keys():
    for j in d[i]:
        if j != "0":
            print(i, d[i])
            break

However, for conciseness I would recommend you check out the any() function, which does exactly what you want: Return true if any of the elements of the iterable are true (when cast to booleans).

Eg:

for i in d.keys():
    if any(j != "0" for j in d[i]):
        print(i, d[i])

(The j is not "0" generator is only necessary because you have string values. For an int array, any(d[i]) would work.)

Even more "Pythonic" would be removing the need for a dictionary lookup:

for i, d_i in d.items():
    if any(j != "0" for j in d_i):
        print(i, d_i)
Christoph Burschka
  • 4,467
  • 3
  • 16
  • 31
  • You should avoid comparing strings with `is not`. Use `!=`. – Austin Feb 18 '19 at 15:34
  • Oh, thanks! I didnt use `break` before, i always had struggles with nested loops because of that! – Flying Thunder Feb 18 '19 at 15:38
  • About "is not": Thanks, the OP's code indeed has another potential bug there; I've now fixed this. (See also https://stackoverflow.com/questions/2988017/string-comparison-in-python-is-vs on this topic.) – Christoph Burschka Feb 18 '19 at 15:38
1

I like the other answers but I feel like you can get away with something like this as well:

for i in d.keys():
    #If there are as many zeroes as there are elements in the list...
    if d[i].count(0) == len(d[i]):
        #...You might as well skip it :)
        continue
    print(d[i])
Luca Giorgi
  • 910
  • 3
  • 14
  • 28
  • This didnt work for me, it only prints the values and it doesnt filter out values that contain only 0s - it works when you count `"0"`, because my lists didnt contain int 0 though, so thanks! – Flying Thunder Feb 18 '19 at 15:35
  • 1
    Ah, right, didn't notice you were using strings instead of ints. Should work with any char/value though as long as you replace the count to whatever you need. – Luca Giorgi Feb 18 '19 at 15:38
1

Have a look at how I could accomplish this.

d = {
    '192.168.244.213': ['8', '4', '3', '1', '6', '5', '3', '2', '6', '5'], 
    '192.168.244.214': ['6', '8', '7', '6', '5', '4', '2', '7', '5', '5'], 
    '192.168.244.215': ['4', '10', '0', '8', '7', '0', '4', '3', '2', '6'], 
    '192.168.244.230': ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
}

for key in d.keys():
    if all( item == '0' for item in d[key]):
        pass
    else:
        print(key, d[key])
cinch
  • 182
  • 10
0

You should use all in this case, consider following example:

digits = ['0', '2', '0', '4', '7', '5', '0', '3', '2', '6']
zeros = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
print(all([k=='0' for k in digits])) #gives False
print(all([k=='0' for k in zeros])) #gives True

Please remember to deliver [k=='0' for k in ...] to all, as delivering list directly would give True for both digits and zeros, as both contain at least one non-empty str (str of length 1 or greater).

Daweo
  • 31,313
  • 3
  • 12
  • 25