Search code examples
pythonlambdalist-comprehension

Python code optimization, list comprehension, lambda function


Please help. I have these for loops:

        path1 = None
        for key, value in items:
            if key.func1() == a and value == b:
                path1 = key.func()
                break

        if path1 is None:
            return False
        for banana in bananas:
            found_match = False
            for key, value in items:
                path2 = key.func()
                if key == banana[0] and value == banana[1] and path1 in path2
                    found_match = True
                    break

            if not found_match:
               ...

Both inner for loops look similar, but the second one has the path1 in path2 condition extra.

Is there a way to write this better? Maybe with a helper function? How would this look using list comprehension or lambda func? Thank you for any help, I am new to this.


Solution

  • By one of your comments, I assume items and bananas are something like this

    a = "apple"
    b = "berry"
    
    itemsdict   = {"a": "b", "c": "d", "apple": "berry", "e": "f"}
    bananasdict = {"a": "b", "apple": "berry", "c": "d"}
    
    items   = itemsdict.items()
    bananas = bananasdict.items()
    

    With a helper function, I made something like this

    def find (thedict, x, y):
        for key, value in thedict:
            if key == x and value == y:
                return key.func()
        return None
    
    path1 = find(items, a, b) 
    if path1 is None:
        return False
    
    found_match = False 
    for bkey, bvalue in bananas:
        path2 = find(items, bkey, bvalue)
        if path2 is not None:
            if path2 in path1:
                found_match = True
                break
    
    if not found_match:
        ...
    

    And you asked for a list comprehension version, this would be kinda straight forward like this

    path1 = [k.func() for k, v in items if k == a and v == b] or None
    # path1 is now a list containing the result of k.func()
    
    if path1 is None:
        return False
    
    found_match = [True for bk, bv in bananas for k, v in items if k == bk and v == bv and k.func() in path1][0]
    # same as aboth, result would be [True], so to get the bool value access it with [0]
    
    if not found_match:
        ...
    

    But I think you mistook list comprehension for what it is. As far as I understood, list comprehension is for creating lists or dictionaries, not work through existing data.

    And for a lambda version, or more overall, you could use the filter() method

    lamb1 = lambda pair: pair[0] == a and pair[1] == b
    lamb2 = lambda pair: pair[0] == a and pair[1] == b and pair[0].func() in path1
    
    def filterfunc1(pair):
        key, value = pair
        if key == a and value == b:
            return True
        return False
    
    def filterfunc2(pair):
        key, value = pair
        if key == a and value == b and key.func() in path1:
            return True
        return False
    
    foundpair1 = dict(filter(filterfunc1, items)) # turn it in a dict containing the matching pairs
    
    # there is no other generic way, known to me, to access a dict without knowing the key name, other than iteration
    # also it just contains one item...
    path1 = None
    for k, v in foundpair1.items():
        path1 = k.func()
    if path1 is None:
        return False
    
    foundpair2 = dict(filter(lamb2, bananas))
    if not foundpair2: # an empty dict equates to False
        ...
    

    So here you can use the lamb1, lamb2 lambda functions or filterfunc1, filterfunc2 functions interchangeably.
    Or put the lambda function in the filter() call directly to make it more compact

    foundpair1 = dict(filter(lambda pair: pair[0] == a and pair[1] == b, items))