使用 Python 来解决慈善机构的业务问题
比较不同的编程语言如何解决同一个问题是一个很有趣的事情,也很有指导意义。接下来,我们就来讲一讲如何用 Python 来解决。
在我这一系列的 第一篇文章 里,我描述了这样子的一个问题,如何将一大批的救助物资分为具有相同价值的物品,并将其分发给社区中的困难住户。我也曾写过用不同的编程语言写一些小程序来解决这样子的小问题以及比较这些程序时如何工作的。
在第一篇文章中,我是使用了 Groovy 语言来解决问题的。Groovy 在很多方面都与 Python 很相似,但是在语法上她更像 C 语言和 Java。因此,使用 Python 来创造一个相同的解决方案应该会很有趣且更有意义。
使用 Python 的解决方案
使用 Java 时,我会声明一个工具类来保存元组数据(新的记录功能将会很好地用于这个需求)。使用 Groovy 时,我就是用了该语言的映射功能,我也将在 Python 使用相同的机制。
使用一个字典列表来保存从批发商处批发来的货物:
1 |
|
大米有一包,每包中有 10 袋大米,意大利面条有十包,每包中有一袋意大利面条。上述代码中,变量 packs
被设置为 Python 字典列表。这与 Groovy 的方法非常相似。关于 Groovy 和 Python 之间的区别,有几点需要注意:
- 在 Python 中,无需关键字来定义变量
packs
,Python 变量初始化时需要设置一个值。 - Python 字典中的词键(例如,
item
、brand
、units
、price
、quantity
)需要引号来表明它们是字符串;Groovy 假定这些是字符串,但也接受引号。 - 在 Python 中,符号
{ ... }
表明一个字典声明; Groovy 使用与列表相同的方括号,但两种情况下的结构都必须具有键值对。
当然,表中的价格不是以美元计算的。
接下来,打开散装包。例如,打开大米的单个散装包装,将产出 10 单元大米; 也就是说,产出的单元总数是 units * quantity
。 Groovy 脚本使用一个名为 collectMany
的方便的函数,该函数可用于展平列表列表。 据我所知,Python 没有类似的东西,所以使用两个列表推导式来产生相同的结果:
1 |
|
第一个列表可理解为(分配给单元)构建字典列表列表。 第二个将其“扁平化”为字典列表。 请注意,Python 和 Groovy 都提供了一个 *
运算符,它接受左侧的列表和右侧的数字 N
,并复制列表 N
次。
最后一步是将这些单元的大米之类的重新包装到篮子(hamper
)中以进行分发。 就像在 Groovy 版本中一样,你需要更具体地了解理想的篮子数,当你只剩下几个单元时,你最好不要过度限制,即可以做一些随机分配:
1 |
|
很好! 重新打包篮子。
1 |
|
一些澄清如上面的注释。
运行此代码时,输出看起来与 Groovy 程序的输出非常相似:
1 |
|
最后一个篮子在内容和价值上有所简化。
结论
乍一看,这个程序的 Python 和 Groovy 版本之间没有太大区别。 两者都有一组相似的结构,这使得处理列表和字典非常简单。 两者都不需要很多“样板代码”或其他“繁杂”操作。
此外,使用 Groovy 时,向篮子中添加单元还是一件比较繁琐的事情。 你需要在单元列表中随机选择一个位置,然后从该位置开始,遍历列表,直到找到一个价格允许的且包含它的单元,或者直到你用完列表为止。 当只剩下几件物品时,你需要将它们扔到最后一个篮子里。
另一个值得一提的问题是:这不是一种特别有效的方法。 从列表中删除元素、极其多的重复表达式还有一些其它的问题使得这不太适合解决这种大数据重新分配问题。 尽管如此,它仍然在我的老机器上运行。
如果你觉得我在这段代码中使用 while
循环并改变其中的数据感到不舒服,你可能希望我让它更有用一些。 我想不出一种方法不使用 Python 中的 map 和 reduce 函数,并结合随机选择的单元进行重新打包。 你可以吗?
在下一篇文章中,我将使用 Java 重新执行此操作,以了解 Groovy 和 Python 的工作量减少了多少,未来的文章将介绍 Julia 和 Go。
via: https://opensource.com/article/20/9/solve-problem-python
作者:Chris Hermansen 选题:lujun9972 译者:zepoch 校对:wxy