0

so I've been trying to figure out how do I convert the main for loop in this code to a list comprehension for efficiency, I've seen some examples, but none of them seem to cater to this sort of scenario. Any help is appreciated!

key = 'abcdefghij'

def getChunks(key):
    ''' Dividing the key into byte sized chunks'''
    currVal = ''
    remainder = ''
    chunks = []
    currVal = ''


    for char in key:
        if len(currVal) == 8:
            chunks.append(currVal)
            currVal = hex(ord(char))[2:]
        else:
            currVal += hex(ord(char))[2:]

    if len(currVal) == 8:
        chunks.append(currVal)
    elif currVal:
        remainder = currVal

    return (chunks, remainder)


print(getChunks(key))

The desired output dividing the input string/key into byte sized chunks of hexadecimal values + any remainder in the following format

>> (['61626364', '65666768'], '696a')

Oh and this too:

for i in range(1, self.hashCount+1): 
    h = hash(item, i) % self.bitArraySize # Generate Hash

    # set the bit True in bit_array 
    self.bitArray[h] = True

for i in range(1, self.hashCount+1): 
            h = hash(item, i) % self.bitArraySize 
            if self.bitArray[h] == False:
                return False

2 Answers2

1

None of these should be list comprehensions. List comprehensions should not have side-effects (they're a functional programming construct and violating functional programming expectations leads to unmaintainable/unreadable code). In all cases, your loops aren't just building a new list element by element in order, they're also making stateful changes and/or building the list out of order.

Side-note: if self.bitArray[h] == False: is a slower, unPythonic way to spell if not self.bitArray[h]:; comparing to True and False is almost always the wrong way to go, per the PEP8 style guide:

Don't compare boolean values to True or False using ==:

 # Correct:
 if greeting:

 # Wrong:
 if greeting == True:
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • Any efficiency tweaks you could suggest, particular for the loop in the function? – Sarwan Shah Jul 01 '20 at 15:18
  • 1
    @SarwanShah: Well, the simplest solution would be to convert from `str` to `bytes` (e.g. `.encode('utf-8')`), then call `.hex()` on that to convert to hex (which would also fix a padding issue your code will have for any ordinal below 16 or above 255). Then just convert it to chunks [as shown in this answer](https://stackoverflow.com/a/312464/364696). Avoids a *lot* of Python level work, and should run significantly faster if you're doing it a lot. Note: Your docstring is misleading: You're not splitting into byte-sized chunks; eight hex characters is a 32 bit word, not a byte. – ShadowRanger Jul 01 '20 at 15:27
  • 1
    @ShadowRanger well, a purist would say a byte can be a 32 bits ^^ (see [wikipedia](https://en.wikipedia.org/wiki/Byte) ) – Oyono Jul 01 '20 at 15:46
1

For question #1

key = 'abcdefghij'

def getChunks(key):
    ''' Dividing the key into byte sized chunks'''
    hex_string = key.encode().hex()
    length = len(hex_string)
    sep = length%8
    return [hex_string[i:i+8] for i in range(0, length-sep, 8)], hex_string[-sep:] if sep !=0 else ''

print(getChunks(key))
Jason Yang
  • 11,284
  • 2
  • 9
  • 23