Home > OS >  Generic function for consequtive element paring by n given to a function with zip
Generic function for consequtive element paring by n given to a function with zip

Time:12-02

I have created a generic function to process consecutive pairings of n length from a given list of integers and give them to a function. It works but I very much dislike the eval in the function but don't know how to change that and still use the zip function.

from typing import List
def consecutive_element_pairing(data: List[int], consecutive_element=3, map_to_func=sum) -> List[int]:
    """
    Return a list with consecutively paired items given to a function that can handle an iterable
    :param data: the list of integers to process
    :param consecutive_element: how many to group consecutively
    :param map_to_func: the function to give the groups to
    :return: the new list of consecutive grouped functioned items
    """
    if len(data) < consecutive_element:
        return []
    return list(map(map_to_func, eval("zip(%s)" % "".join((map(lambda x: "data[%d:], " % x, range(consecutive_element)))))))

given a list of e.g.:

values = [1, 2, 3, 4, 5, 6, 7, 8, 9]

and I call it like this:

print("result:", consecutive_element_pairing(values))
[6, 9, 12, 15, 18, 21, 24]

This is correct as it correctly groups ((1,2,3),(2,3,4),(3,4,5)...) them by consecutive groups of 3 and then sums those.

The trouble I have with my code is the eval statement on the generated string of zip(data[0:], data[1:], data[2:], ).

I have no idea how to do this a different way as zip with a list inside does something completely different.

Can this be done differently while still using zip?

Any help is appreciated.

I know how to do this in many different ways but the challenge for myself was the usage of zip here :-) and making it a "generic" function.

CodePudding user response:

You can simply use zip(*(values[i:] for i in range(N))):

Example

values = [1, 2, 3, 4, 5, 6, 7, 8, 9]
N = 3
list(zip(*(values[i:] for i in range(N))))

# [(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7), (6, 7, 8), (7, 8, 9)]

A slightly improved variant for long lists and large N might be:

zip(*(values[i:len(values)-(N-i) 1] for i in range(N)))

function

from typing import List
def consecutive_element_pairing(data: List[int], consecutive_element=3, map_to_func=sum) -> List[int]:
    N = consecutive_element
    return list(map(map_to_func, zip(*(data[i:len(data)-(N-i) 1] for i in range(N)))))

consecutive_element_pairing(values)
# [6, 9, 12, 15, 18, 21, 24]
  • Related