简体   繁体   中英

How to generate a list of numbers where all digits are even?

I have a list of numbers generated using list comprehension but would like to have python examine the output and only print the results if every digit in the number is an even number (eg 266). If the number is even, for example 218 but every digit not divisible by 2 then it should not print. Could anyone please help?

Here is my code:

jail=[res for res in range(200,300)if res % 2 ==0 ]
print(jail)

With strings and sets

You could define a set of acceptable digits and filter the integers that only use those digits:

>>> allowed_digits = set('02468')
>>> [i for i in range(200,300) if set(str(i)) <= allowed_digits]
[200, 202, 204, 206, 208, 220, 222, 224, 226, 228, 240, 242, 244, 246, 248, 260, 262, 264, 266, 268, 280, 282, 284, 286, 288]

The desired property isn't really defined for a number but for its decimal representation. I'd say it makes sense to use str() in this case.

With arithmetics

It's also possible to use arithmetics to check if every digit is even, for example with a recursive function:

def all_even(i):
    if i == 0:
        return True
    return (i % 10) % 2 == 0 and all_even(i // 10)

print(all_even(123456))
# False
print(all_even(24680))
# True

It can be used this way:

>>> [i for i in range(200,300) if all_even(i)]
[200, 202, 204, 206, 208, 220, 222, 224, 226, 228, 240, 242, 244, 246, 248, 260, 262, 264, 266, 268, 280, 282, 284, 286, 288]

Performance

Jared Goguen's excellent answer is by far the fastest:

In [46]: %timeit [int(''.join(t)) for t in product('02468', repeat=5)]
2.19 ms ± 12.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

It makes sense because it generates the list directly, without having to filter anything.

Then comes the all_even method:

In [17]: %timeit [i for i in range(100000) if all_even(i)]
69.5 ms ± 133 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

followed by the string and set method:

In [15]: %timeit [i for i in range(100000) if set(str(i)) <= allowed_digits]
104 ms ± 167 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

followed by @jmd_dk's answer :

In [14]: %timeit [res for res in range(100000) if all(int(digit)%2 == 0 for digit in str(res))]
245 ms ± 1.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

followed by Jamie Counsell's answer :

In [16]: %timeit [res for res in range(1,100000) if all((int(res/math.pow(10, power) % 2) == 0) for power in range(0, int(math.log10(res)) + 1))]
447 ms ± 2.02 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

I'd recommend generating the numbers that you want directly, rather than filtering the list afterwards. The function itertools.product can be used to generate all of the suffices, (0, 0) , (0, 2) , ..., and so on. Then, just add 200 to each one.

from itertools import product

vals = [200 + int(''.join(t)) for t in product('02468', repeat=2)]

This is somewhat extensible. Let's say you wanted to generate all of the four digit only-even numbers starting with 2000 and ending with 4888, then you could use:

vals = [int(''.join(t)) for t in product(*(('24',) + ('02468',) * 3))]

You can then filter the result afterwards if you want less clean bounds.

This leaves the original list as is and prints each number on its own:

jail = [res for res in range(200,300)if res % 2 ==0 ]
for number in jail:
    if all(int(digit)%2 == 0 for digit in str(number)):
        print(number)

If you want only these special numbers in the jail list, simply put the condition into the creation of the list:

jail = [res for res in range(200,300) if all(int(digit)%2 == 0 for digit in str(res))]

These solutions rely on the fact that each digit can be obtained by iteration over the str representation of the integers.

If list comprehension is not necessarily required, below is the function which can be used to return a list of numbers whose all digits are even.

def only_even_digits_num(my_list):
my_list_cp = my_list.copy()
for num in my_list_cp:
    remove_flag = 0
    for i in str(num):
        if int(i)%2==0 and remove_flag==0:
            pass
        else:
            remove_flag = 1
            if num in my_list:
                my_list.remove(num)
return my_list

test_list = [0,1,2,3,102,201,202,88,636] print(only_even_digits_num( test_list ))

returns

[0, 2, 202, 88]

I tried to do it using List Comprehension but I didn't succeeded. If someone can do it then I will further update my answer with credit and reference.

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