TheStrangeQuark
TheStrangeQuark

Reputation: 2405

List comprehension to find all multiples of each number in list less than a number

I'm trying to write a function that will find all numbers that are a multiple of at least one number in a list where the multiple is less than a certain number. Here's what I've tried so far:

def MultiplesUnderX(MultArray,X):
    '''
    Finds all the multiples of each value in MultArray that
    are below X.
    MultArray: List of ints that multiples are needed of
    X: Int that multiples will go up to
    '''
    return [i if (i % x == 0 for x in MultArray) else 0 for i in range(X)]

For example, MultiplesUnderX([2,3],10) would return [2,3,4,6,8,9]. I'm a little unsure how to do this with the for loop inside of the list comprehension.

Upvotes: 4

Views: 3888

Answers (3)

Ajax1234
Ajax1234

Reputation: 71461

You can use the Python any() function to check if there is at least one instance of a divider in MultArray:

def MultiplesUnderX(MultArray,X):

    return [i for i in range(X) if any(i % x == 0 for x in MultArray)]

Upvotes: 8

Paul
Paul

Reputation: 10883

Another version of this algorithm which may be more efficient if the list is mostly co-prime, you can just use range(i, X, i) to generate only the multiples of i, then use heapq.merge to merge the iterators such that the iterator returned is sorted.

The last step is to eliminate duplicates as you go:

import heapq

def all_multiples(multi_list, max_N):
    gens = []
    for fac in sorted(set(multi_list)):
        # In Python 3 this is a generator of all multiples of "fac" less
        # than max_N. In Python 2 use xrange
        gens.append(range(fac, max_N, fac))

    # This will do a heap merge on the generators (which are already sorted)
    o = heapq.merge(*gens)
    last = None
    for val in o:
        if val != last:
            yield val
            last = val


if __name__ == "__main__":
    multi_list = [2, 4, 7]
    print(list(all_multiples(multi_list, 12)))
    # [2, 4, 6, 7, 8, 10]

Upvotes: 0

foslock
foslock

Reputation: 3939

You can use the Python built-in function any which returns True if the iterable passed in contains any truth-y values in combination with a conditional at the end of the list comprehension limiting the list to only elements that satisfy the any call.

def get_multiples_under(factors, max):
    return [i for i in xrange(1, max) if any(i % factor == 0 for factor in factors)]

Your desired output is shown as such:

multiples = [2, 3]
print get_multiples_under(multiples, 10)
# [2, 3, 4, 6, 8, 9]

Upvotes: 1

Related Questions