简体   繁体   中英

python loop to find the largest integer from a list

I wrote a script to pull down a list of aws tags and then read the last octect and tell me which one is the highest IP. For example. here is the list of tags that are returned:

['vlslabmc, 172.16.0.13/24', 'vlslabmc,172.16.0.5/24', 'vlslabmc,172.16.0.3/24', 'vlslabmc,172.16.0.12/24', 'vlslabmc,172.16.0.16/24', 'vlslabmc,172.16.0.6/24', 'vlslabmc,172.16.0.1/24', 'vlslabmc,172.16.0.11/24', 'vlslabmc,172.16.0.15/24', 'vlslabmc,172.16.0.17/24', 'vlslabmc,172.16.0.4/24', 'vlslabmc,172.16.0.7/24', 'vlslabmc,172.16.0.10/24', 'vlslabmc,172.16.0.9/24', 'vlslabmc,172.16.0.8/24', 'vlslabmc,172.16.0.2/24', 'vlslabmc,172.16.0.14/24']

Here's my code to workout the largest IP from the tagLis (note that the largest is 17, 172.16.0.17)

 21 def findLargestIP():
 22         for i in tagList:
 23                 #remove all the spacing in the tags
 24                 ec2Tags = i.strip()
 25                 #seperate any multiple tags
 26                 ec2SingleTag = ec2Tags.split(',')
 27                 #find the last octect of the ip address
 28                 fullIPTag = ec2SingleTag[1].split('.')
 29                 #remove the CIDR from ip to get the last octect
 30                 lastIPsTag = fullIPTag[3].split('/')
 31                 lastOctect = lastIPsTag[0]
 32                 ipList.append(lastOctect)
 33                 largestIP  = int(ipList[0])
 34                 for latestIP in ipList:
 35                         if int(latestIP) > largestIP:
 36                                 largestIP = latestIP
 37         return largestIP

I'm not sure why.. but when I print the value of largestIP it always prints out 16. Ive gone through the code it should have worked (I'm avoiding using the max function as I'm just learning to code)

Any help as aways is greatly appreciated.

Thanks

Edit with the answer below, and a question

Ok so thanks to a clue from cmarie I got it working the problem was mainly

33                 largestIP  = int(ipList[0])

Here's the code running before with an added print statement on the list append:

'13']
['13', '5']
['13', '5', '3']
['13', '5', '3', '12']
['13', '5', '3', '12', '16']
16
['13', '5', '3', '12', '16', '6']
16
['13', '5', '3', '12', '16', '6', '1']
16
['13', '5', '3', '12', '16', '6', '1', '11']
16
... ...
['13', '5', '3', '12', '16', '6', '1', '11', '15', '17', '4', '7', '10', '9', '8', '2']
    16
['13', '5', '3', '12', '16', '6', '1', '11', '15', '17', '4', '7', '10', '9', '8', '2', '14']
16

Basically what was happening is that during this loop :

33                 largestIP  = int(ipList[0])
 34                 for latestIP in ipList:
 35                         if int(latestIP) > largestIP:
 36                                 largestIP = latestIP

The loop stops at the 1st largest integer. in this case that is 16. *I'm not sure why it does but it does

Here's the working code:

19 def findLargestIP():
 20         ipList =[]
 21         for i in tagList:
 22                 #remove all the spacing in the tags
 23                 ec2Tags = i.strip()
 24                 #seperate any multiple tags
 25                 ec2SingleTag = ec2Tags.split(',')
 26                 #find the last octect of the ip address
 27                 fullIPTag = ec2SingleTag[1].split('.')
 28                 #remove the CIDR from ip to get the last octect
 29                 lastIPsTag = fullIPTag[3].split('/')
 30                 lastOctect = lastIPsTag[0]
 31                 ipList.append(int(lastOctect))
 32                 print ipList
 33                 largestIP  = 0
 34                 for latestIP in ipList:
 35                         if latestIP > largestIP:
 36                                 largestIP = latestIP
 37                                 print latestIP
 38         print largestIP
 39         return largestIP

and the result:

[13, 5, 3, 12, 16]
13
16
[13, 5, 3, 12, 16, 6]
13
16
[13, 5, 3, 12, 16, 6, 1]
13
16
[13, 5, 3, 12, 16, 6, 1, 11]
13
16
[13, 5, 3, 12, 16, 6, 1, 11, 15]
13
16
[13, 5, 3, 12, 16, 6, 1, 11, 15, 17]
13
16
17

Note it found 17.

Although other people have already provide you some alternative ways to find the answer, if you want to keep using your program, here is some way of fixing it:

def findLargestIP():
    ipList = []
    for i in tagList:
        #remove all the spacing in the tags
        ec2Tags = i.strip()
        #seperate any multiple tags
        ec2SingleTag = ec2Tags.split(',')
        #find the last octect of the ip address
        fullIPTag = ec2SingleTag[1].split('.')
        #remove the CIDR from ip to get the last octect
        lastIPsTag = fullIPTag[3].split('/')
        lastOctect = lastIPsTag[0]
        ipList.append(int(lastOctect))
    largestIP  = 0
    for latestIP in ipList:
        if latestIP > largestIP:
            largestIP = latestIP
    return largestIP

The differences from this and your program are that here I:

  • set ipList = []
  • make ipList contain integers, rather than strings
  • set largestIP = 0 , instead of taking the first number of the ipList (since you shouldn't assume the list is sorted)
  • remove the loop to find the largest number outside the first loop [on the tagList ] - just for eliminating unnecessary iterations

If I would do that task, however, I would try to use regular expressions. Here is a way to do it:

import re
def alternativeFindLargestIP():
    ipList = re.findall(r'(?<=\.)\d+(?=/)', ' '.join(tagList))
    ipList = [int(num) for num in ipList]
    return max(ipList)

Why are doing this so complex. Here is oneliner for this

ip_list = ['vlslabmc, 172.16.0.13/24', 'vlslabmc,172.16.0.5/24', 'vlslabmc,172.16.0.3/24', 'vlslabmc,172.16.0.12/24', 'vlslabmc,172.16.0.16/24', 'vlslabmc,172.16.0.6/24', 'vlslabmc,172.16.0.1/24', 'vlslabmc,172.16.0.11/24', 'vlslabmc,172.16.0.15/24', 'vlslabmc,172.16.0.17/24', 'vlslabmc,172.16.0.4/24', 'vlslabmc,172.16.0.7/24', 'vlslabmc,172.16.0.10/24', 'vlslabmc,172.16.0.9/24', 'vlslabmc,172.16.0.8/24', 'vlslabmc,172.16.0.2/24', 'vlslabmc,172.16.0.14/24']

largestIP = max(ip_list, key=lambda i: int(i.split('/')[0].split('.')[-1]))

The code is quite convoluted (much more than needed) but the error is that ipList gets filled with strings and then its elements are compared with an integer.

This in Python 2 was a silent source of problems (you got a nonsensical but stable True / False result when comparing different types instead of an error) and in Python 3 it became an error.

a much simpler implementation would in my opinion be:

return max(int(x.split(",")[1].split("/")[0].split(".")[-1])
           for x in taglist)

with the meaning:

  • split(",")[1] to take the part after the comma
  • split("/")[0] to take the part before the slash
  • split(".")[-1] to take the last part of IP address
  • int(...) to convert to integer
  • max(... for x in taglist to do this for all elements and keeping the max

or using a regexp with

return max(int(re.match(".*?([0-9]+)/", x).group(1))
           for x in taglist)

So I had to refactor your code a little bit. I assumed ipList was an empty list. Are you sure you tested to see if it actually ran? Specifically your if statement

if int(latestIP) > largestIP:
    largestIP = latestIP

would return a

TypeError: unorderable types: int() > str()

because you would be assigning a string to largestIP and then in the next iteration, you would compare a string with an int. Aside from that, your code seems functional. It returns 17 as the largest last octet for me which seems right.

If your intention is to return the largest last octet of your list of ip addresses, you might want to approach this a little bit differently.

Option 1: Accumulate list of IP Addresses first

Instead of nesting a for loop in your loop to iterate through all the tags, you can first just accumulate the tags and then go through and find the max. This way, you go through the tag list once, and then the ip list once, instead of going through your entire ip list each time you iterate through your tag list.

Option 2: Create a list of only the last octet

Similar to option 1, you would iterate through your tagList and accumulate all the last octets of the ip addresses casted to ints into a list, instead of the entire ip address. In a loop afterwards, you can call max on the list with the octets (I'm guessing you want to avoid this).

Option 3: Have a running greatest value

I think this is the best solution. As you're going through the tag list, you can keep a variable that will have the greatest last octet so far. This way you only need to loop through the tag list once, and still come out with the greatest last octet thus far.

If you want to grab the entire IP address, options 1 and 3 would still work, but for option 2, you might want to look into python dictionaries .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM