简体   繁体   中英

Better way to filter two list of lists by checking length of the inner lists

Given two list of lists, the goal is to filter out the list based on the length of the inner list.

The length criteria is set by the user, ie

>>> x = [[1,2,3], [1,2,3,4,5,6], [1,2,3,4,5], [1,2,5,6]]
>>> y = [[9,8,7], [9,4,3], [9,4,2], [9,4,2,3]]

>>> mini, maxi = 1, 5 # Accepts inner list length between 1 to 4. 

>>> def my_and_filter(x, y):
...     for i, j in zip(x,y):
...         if mini < len(i) < maxi and mini < len(j) < maxi:
...             yield (i, j)


>>> list(myfilter(x, y))
[([1, 2, 3], [9, 8, 7]), ([1, 2, 5, 6], [9, 4, 2, 3])]

The above is for case where the filter needs to be strict and apply to both lists of lists.

But there's another case where, it only needs to be applied to either:

>>> def myfilter(x, y):
...     for i, j in zip(x,y):
...         if mini < len(i) < maxi or mini < len(j) < maxi:
...             yield (x, y)
... 

>>> list(myfilter(x, y))
[([1, 2, 3], [9, 8, 7]), ([1, 2, 3, 4, 5, 6], [9, 4, 3]), ([1, 2, 3, 4, 5], [9, 4, 2]), ([1, 2, 5, 6], [9, 4, 2, 3])]

My questions are

  • is it possible to combine the two operators? and
  • **is there a better way to write this condition mini < len(i) < maxi and mini < len(j) < maxi ?

I've tried to combine the two operators with an argument the following but I'll like to know if there's a better way of doing so:

>>> import operator 

>>> def my_filter(x, y, strict=True):
...     _op = operator.__and__ if strict else operator.__or__
...     for i, j in zip(x,y):
...         if _op(mini < len(i) < maxi, mini < len(j) < maxi):
...             yield (i, j)
... 


>>> list(my_filter(x,y))
[([1, 2, 3], [9, 8, 7]), ([1, 2, 5, 6], [9, 4, 2, 3])]
>>> list(my_filter(x,y, False))
[([1, 2, 3], [9, 8, 7]), ([1, 2, 3, 4, 5, 6], [9, 4, 3]), ([1, 2, 3, 4, 5], [9, 4, 2]), ([1, 2, 5, 6], [9, 4, 2, 3])]

An alternative is to return a generator for each case...

def myfilter(x, y, min_l, max_l, strict=True):
    if strict:
        return ((i, j) for i, j in zip(x, y) if min_l <= len(i) <= max_l and min_l <= len(j) <= max_l)
    else:
        return ((i, j) for i, j in zip(x, y) if min_l <= len(i) <= max_l or min_l <= len(j) <= max_l)

I'm not sure if you want the minimum length to be applied as you have it (?) If you want mini to be the minimum length, it seems more correct to use the <= operator in the expressions.

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