【问题标题】:How to filter a list of lists based on a variable set of conditions with Python?如何使用 Python 根据一组可变条件过滤列表列表?
【发布时间】:2018-05-25 23:11:43
【问题描述】:

与此post相关的问题。

我需要帮助来根据一组可变条件过滤列表列表。

这里是列表的摘录:

ex = [
    # ["ref", "type", "date"]
    [1, 'CB', '2017-12-11'],
    [2, 'CB', '2017-12-01'],
    [3, 'RET', '2017-11-08'],
    [1, 'CB', '2017-11-08'],
    [5, 'RET', '2017-10-10'],
]

我想应用像list(filter(makeCondition, ex)) 这样的最终处理,其中makeCondition(myList, **kwargs) 函数返回一个可以过滤列表的布尔值。

我无法按照post 中的建议构建此函数,因为 **kwargs 字典中定义的条件数量是可变的。

条件集示例:

conditions = {"ref": 3}
conditions = {"ref": 1, "type": "CB"}

这是一个开始:

def makeConditions(myList, **p):

    # For each key:value in the dictionnary
    for key, value in p.items():

        if key == "ref":
            lambda x: x[0] == value
        elif key == "type":
            lambda x: x[1] == value
        elif key == "date":
            lambda x: x[2] == value

    # return chained conditions...

list(filter(makeConditions, ex))

我不明白各种 cmets 试图在上面提到的帖子中给出的合乎逻辑的想法......我是否必须为每个子列表执行 filter() 函数,或者是否可以为整个全局列表执行此操作?非常欢迎任何建议!

【问题讨论】:

  • 它是否总是有参考、类型和日期,还是可变的?
  • conditions 变量确实是变量,如帖子所示。子列表的内容始终与 3 个对象保持一致:ref、type 和 date。

标签: python python-3.x filtering


【解决方案1】:

你快到了,想法是创建一个包含检查所需条件的函数的列表,一旦你有了它们,你就可以在他们必须检查的列表上调用这些函数并使用all 函数来检查如果所有这些都被评估为True,请注意使用部分,因此filter调用中的函数仅获取数据列表;检查这个:

from functools import partial

ex = [
    # ["ref", "type", "date"]
    [1, 'CB', '2017-12-11'],
    [2, 'CB', '2017-12-01'],
    [3, 'RET', '2017-11-08'],
    [1, 'CB', '2017-11-08'],
    [5, 'RET', '2017-10-10'],
]

conditions  = {"ref": 3}
conditions2 = {"ref": 1, "type": "CB"}

def apply(data, *args):
"""
same as map, but takes some data and a variable list of functions instead
it will make all that functions evaluate over that data
"""
  return map(lambda f: f(data), args)


def makeConditions(p, myList):
    # For each key:value in the dictionnary
    def checkvalue(index, val, lst):
      return lst[index] == val
    conds = []
    for key, value in p.items():
        if key == "ref":
            conds.append(partial(checkvalue, 0, value))
        elif key == "type":
            conds.append(partial(checkvalue, 1, value))
        elif key == "date":
            conds.append(partial(checkvalue, 2, value))
    return all(apply(myList, *conds)) # does all the value checks evaluate to true?

#use partial to bind the conditions to the makeConditions function
print(list(filter(partial(makeConditions, conditions), ex)))
#[[3, 'RET', '2017-11-08']]
print(list(filter(partial(makeConditions, conditions2), ex)))
#[[1, 'CB', '2017-12-11'], [1, 'CB', '2017-11-08']]

你有一个live example

我必须为每个子列表执行 filter() 函数还是可以为整个全局列表执行此操作?

Filter 遍历所有列表,为每个元素应用一个函数,如果函数计算结果为 True,则该元素将在结果中提醒,因此 filter 对整个全局列表起作用

【讨论】:

  • 非常感谢@Daniel Sanchez!在你的建议中对我来说有一些新的东西,无论如何它工作得很好。我必须阅读有关partial() 函数的文档。我不明白checkvalue() 函数如何找到index 参数。
  • @wiltomap,部分将值绑定到函数参数,返回另一个函数,这些参数用这些值固定,所以当我调用 partial(checkvalue, 0, value) 时,我创建了一个与你的 lambdas 一样的函数,只是为了以后使用。
【解决方案2】:

我会简单地创建一个返回条件的函数:

def makeConditions(**p):
    fieldname = {"ref": 0, "type": 1, "date": 2 }
    def filterfunc(elt):
        for k, v in p.items():
            if elt[fieldname[k]] != v: # if one condition is not met: false
                return False
        return True
    return filterfunc

那么你可以这样使用它:

>>> list(filter(makeConditions(ref=1), ex))
[[1, 'CB', '2017-12-11'], [1, 'CB', '2017-11-08']]
>>> list(filter(makeConditions(type='CB'), ex))
[[1, 'CB', '2017-12-11'], [2, 'CB', '2017-12-01'], [1, 'CB', '2017-11-08']]
>>> list(filter(makeConditions(type='CB', ref=2), ex))
[[2, 'CB', '2017-12-01']]

【讨论】:

  • 它看起来不错,而且短得多......谢谢@Serge Ballesta!我会仔细看看然后回来。
猜你喜欢
  • 2019-08-03
  • 1970-01-01
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 2020-08-16
  • 1970-01-01
相关资源
最近更新 更多