【问题标题】:Python lambda functions, iterating over a tuple and a listPython lambda 函数,遍历元组和列表
【发布时间】:2020-04-27 15:58:03
【问题描述】:

假设你有一个包含属性的类表: 记录(字典列表) 和作为每个表的主键的键(就像 SQL 一样) - 元组

我需要编写一个 lambda 函数,它接受一个新行,然后如果新行中键的所有值都吐出 True 或 False 已经在表中了

例如:

# Table: orders

keys = ('product_id', 'customer_id')

records: [{'product_id': 51, 'customer_id' : 10, 'units':9},
          {'product_id': 32, 'customer_id' : 11, 'units':33},
          {'product_id': 39, 'customer_id' : 47, 'units':2}]

现在我们要检查的新行是:

{'product_id': 51, 'customer_id' : 10, 'units': 77 }

这将返回 True,因为 product_id==51customer_id==10 就像记录中的第一个字典(单位无关紧要,因为它不是键)。

但是:

{'product_id': 51, 'customer_id' : 11, 'units':9}

将返回False,因为没有product_id==51customer_id==11 的行

我们必须使用 lambda 函数(我们不必使用过滤器,只是一个提示)
我已经尝试了许多不同的“攻击”这个问题的方法,但我无法同时遍历键列表和元组......

contains_key = lambda self, new_row: list(filter(  
  (lambda con: con[self.__key]), 
  [record for record in self.__records] 
))

解释:self 是我们对其进行操作的表,new_row 是要检查的行(字典)
self.__keys 是键的元组(如 sql 中的主键),self.__records 是字典列表="""sql 表中的行""")
该函数位于类 Table 中(这就是它采用“自我”形式的原因)

class Table:
    def __init__(self, key_set):
        self.__key = tuple(key_set)
        self.__records = []

    def add_record(self, new_record):
        self.__records.append(new_record)

【问题讨论】:

  • "需要写一个 lambda 函数" - 为什么?
  • x = lambda ...有点失去了lambdas的意义......
  • @HeapOverflow 这是大学的任务。我不知道你为什么要使用 lambdas 这么糟糕的方式,他们实际上在任务中说过(只是解释如何编写它)
  • 我假设这是针对 CS 或编程课程的某种分配,这就是您尝试将其编写为 lambda 的原因。这实际上是普通 Python 编程中的一种反模式,您不应该将 lambda 分配给名称,在这种情况下,def 几乎总是更好。
  • @Grismar 正确,先生。 :)

标签: python python-3.x lambda


【解决方案1】:

这是一个规范的答案:

def has_row(records, keys, row):
    return any(
        all(row[k] == x[k] for k in keys)
        for x in records
    )

转换为“lambda 函数”很简单:

has_row = (lambda records, keys, row:
    any(
        all(row[k] == x[k] for k in keys)
        for x in records
    )
)

如果您未被“允许”使用anyall,则可以按如下方式替换它们:

any = (lambda xs:
    bool(next(filter(lambda x: x, xs), False))
)

# Alternatively, without using next:
any = (lambda xs:
    len(list(filter(lambda x: x, xs))) != 0
)

all = (lambda xs:
    len(list(filter(lambda x: not x, xs))) == 0
)

【讨论】:

  • @HeapOverflow 哎呀,我最近写了一些 Haskell 后,简直不敢相信我点错了……
  • @HeapOverflow 你的意思是像filter(None, xs)?要记住的巧妙技巧,但我会把它留给已经有点困惑的OP。 ;)
  • 是的,我的意思是None。另一个想法:all = lambda xs: min(map(bool, xs), default=True)any = lambda xs: max(map(bool, xs), default=False)
【解决方案2】:

简单地使用anyall 就可以了:“检查any 记录的all 键是否与新记录相同”

print(any(all(new_record[key] == record[key] for key in keys) for record in records))

这些功能的好处是短路:每当键不匹配时 - 记录将被跳过,而当记录匹配时 - 将不再检查记录。


我会把它留给你作为练习,把它变成lambda :)

【讨论】:

  • 嗨,如果订单中有这样的字典: order3 = {'customer_id' : '13','product_id' : '1234-5', 'units': 9 } 我们用另一个字典测试它: order4 = {'customer_id': '13', 'product_id':'1234-5', 'units':3} 最后的答案是“假”,应该是真的,我不知道为什么不过在我看来还可以。
  • 等等,我的错。它工作得很好。非常感谢您,当我阅读此功能时,我现在清楚地了解了该模式。非常感谢!
【解决方案3】:

好像是这样的:

class Table:
    def __init__(self, key):
        # using the __ in an odd way
        self.__key = key
        self.__records = []

    # only using lambda because you must, it's pointless
    contains_key = lambda self, record: any(all(record[f] == r[f] for f in self.__key) for r in self.__records)

    def add(self, record):
        if not self.contains_key(record):
            self.__records.append(record)
        else:
            raise Exception('duplicate key')


t = Table(('product_id', 'customer_id'))
t.add({'product_id': 51, 'customer_id': 10, 'units': 9})
t.add({'product_id': 32, 'customer_id': 11, 'units': 33})
t.add({'product_id': 39, 'customer_id': 47, 'units': 2})
# fails
t.add({'product_id': 39, 'customer_id': 47, 'units': 2})

但如果这是他们教你的,我会寻找更好的课程。

如果我替换:

# fails
t.add({'product_id': 39, 'customer_id': 47, 'units': 2})

t.add({'customer_id': '13', 'product_id': '1234-5', 'units': 9})
print(t.contains_key({'customer_id': '13', 'product_id': '1234-5', 'units': 3}))

结果是True

【讨论】:

  • 嗨,如果我有字典:{'customer_id' : '13','product_id' : '1234-5', 'units': 9 } 并尝试使用:{' customer_id': '13', 'product_id':'1234-5', 'units':3} 它返回 false,但它应该返回 true,因为 customerid 13 和产品 id 1234-5 已经在表中
  • 不确定您做错了什么,但请参阅答案中的编辑。
  • 等等,我的错。它工作得很好。非常感谢您,当我阅读此功能时,我现在清楚地了解了该模式。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2013-04-07
  • 1970-01-01
相关资源
最近更新 更多