简体   繁体   中英

How to get only even numbers from list

def only_evens(lst):
    """ (list of list of int) -> list of list of int

    Return a list of the lists in lst that contain only even integers. 

    >>> only_evens([[1, 2, 4], [4, 0, 6], [22, 4, 3], [2]])
    [[4, 0, 6], [2]]
    """

    even_lists = []

    for sublist in lst:
        for i in sublist:
            if i % 2 == 0:
                even_lists.append(i)
    return even_lists

I can't do this because it returns everything in one list[] But how can I return sublist that consists only with even integers?

I would split it into two functions: one which checks if a list contains only even numbers, and the other one is your main function (I renamed it to get_even_lists() ), which gets all the even lists from a list of lists:

def only_even_elements(l):
    """ (list of int) -> bool

    Return a whether a list contains only even integers.

    >>> only_even_elements([1, 2, 4])  # 1 is not even
    False
    """
    for e in l:
        if e % 2 == 1:
            return False
    return True

def get_even_lists(lst):
    """ (list of list of int) -> list of list of int

    Return a list of the lists in lst that contain only even integers. 

    >>> only_evens([[1, 2, 4], [4, 0, 6], [22, 4, 3], [2]])
    [[4, 0, 6], [2]]
    """
    # return [l for l in lst if only_even_elements(l)]
    even_lists = []
    for sublist in lst:
        if only_even_elements(sublist):
            even_lists.append(sublist)
    return even_lists

Although, this could be done with for / else :

def get_even_lists(lst):
    """ (list of list of int) -> list of list of int

    Return a list of the lists in lst that contain only even integers. 

    >>> only_evens([[1, 2, 4], [4, 0, 6], [22, 4, 3], [2]])
    [[4, 0, 6], [2]]
    """
    even_lists = []
    for sublist in lst:
        for i in sublist:
            if i % 2 == 1:
                break
        else:
            even_lists.append(sublist)
    return even_lists

Or as others have suggested, a one-liner:

def get_even_lists(lst):
    """ (list of list of int) -> list of list of int

    Return a list of the lists in lst that contain only even integers. 

    >>> only_evens([[1, 2, 4], [4, 0, 6], [22, 4, 3], [2]])
    [[4, 0, 6], [2]]
    """
    return [sublst for sublst in lst if all(i % 2 == 0 for i in sublst)]

But let's be honest here: while it's arguable that using two functions might be a bit longer and not as "cool" as the other two solutions, it's reusable, easy to read and understand, and it's maintainable. I'd argue it's much better than any other option out there.

You could also do this using functional programming:

def only_evens(lst):
    return filter(lambda ls: all(map(lambda n: not n & 1, ls)), lst)

EDIT

As per JF Sebastian's recommendation, I split this into three functions:

is_odd = lambda n: n & 1
all_even = lambda arr: not any(map(is_odd, arr))
only_evens = lambda arr: filter(all_even, arr)

is_odd one checks if a number is odd using bitwise operations for efficiency. all_even checks if a list has all even numbers and returns a boolean. only_evens takes a list of list of integers and returns a list of the lists that contain only even integers.

I would think not about what you are keeping, but about what you're removing (all lists containing an odd number). Something like

import copy

list_copy = copy.copy(lists)
def only_evens(list_copy):
    for l in list_copy:
        for i in l:
            if i % 2 != 0:
                list_copy.remove(l)
                break
    return(list_copy) 

(which emphasizes readability over conciseness, to be sure.)

I guess you can divide your problem into small parts.

def contains_only_evens(lst):
    return sum([x%2 for x in lst]) == 0

def only_evens(lst):
    for sublist in lst:
        if not contains_only_evens(sublist):
            lst.remove(sublist)
    return lst

In this way you can:

  • iterate over a list and its sublists
  • check if the list contains any odd integer
  • keep only sublist with no odds values

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