如何从 access 中导入的数据创建一组列表?
Posted
技术标签:
【中文标题】如何从 access 中导入的数据创建一组列表?【英文标题】:How do I create a group of lists from imported data from access? 【发布时间】:2014-09-27 07:39:02 【问题描述】:我已经阅读了几篇文章,但没有什么能帮助我解决这个问题。我找到了有关每种可能组合的信息,但我发现的是每个列表中所有值的组合,而不是列表本身。 (这里是我之前关于导入访问文件的问题的链接,以了解我正在做的更多示例:How do I import an .accdb file into Python and use the data?)。
假设我有一个从 Access 导入的列表。
CreatureID Name Atk Def HP Type BattlePower
---------- -------- ------ ------ ----- --------- -----------
1 Snake 1000 500 200 Reptile 20
2 Mouse 500 200 100 Mammal 20
3 Turtle 200 2000 2000 Amphibian 40
4 Cat 1500 700 400 Mammal 20
5 Dog 1700 800 600 Mammal 40
6 Bird 100 100 200 Bird 20
7 Badger 2000 1500 1000 Mammal 40
8 Squirrel 300 200 200 Mammal 20
我一直试图弄清楚如何使用导入的访问数据将每个生物信息存储为一组列表。
creatureList = [ [1, 'Snake', 1000, 500], [2, 'Mouse', 500, 200],
[3, 'Turtle', 200, 2000], [4, 'Cat', 1500, 700],
[5, 'Dog', 1700, 800], [6, 'Bird', 100, 100],
[7, 'Badger', 2000, 1500] ]
获得列表后,棘手的部分是我需要创建所有可能的生物组合中的 5 个组。 (可能不需要上一步来完成此操作,但不确定)。
group1List = [ [1, 'Snake', 1000, 500], [2, 'Mouse', 500, 200],
[3, 'Turtle', 200, 2000], [4, 'Cat', 1500, 700],
[5, 'Dog', 1700, 800] ]
group2List = [ [1, 'Snake', 1000, 500], [2, 'Mouse', 500, 200],
[3, 'Turtle', 200, 2000], [4, 'Cat', 1500, 700],
[6, 'Bird', 100, 100] ]
group3List = [ [1, 'Snake', 1000, 500], [2, 'Mouse', 500, 200],
[3, 'Turtle', 200, 2000], [4, 'Cat', 1500, 700],
[7, 'Badger', 2000, 1500]]
group4List = [ [2, 'Mouse', 500, 200], [3, 'Turtle', 200, 2000],
[4, 'Cat', 1500, 700], [5, 'Dog', 1700, 800],
[6, 'Bird', 100, 100] ]
group5List = [ [2, 'Mouse', 500, 200], [3, 'Turtle', 200, 2000],
[4, 'Cat', 1500, 700], [5, 'Dog', 1700, 800],
[7, 'Badger', 2000, 1500] ]
接下来的几个步骤我希望能够将每个组的总攻击力和防御力相加,并能够将它们相互比较以找到总统计数据最高的组。
group1total = [4900, 4200]
group2total = [3300, 3500]
group3total = [5200, 4900]
编辑
试图让它变得比需要的更难。这是工作代码。
LIST = []
import pypyodbc
import itertools
import operator
pypyodbc.lowercase = False
conn = pypyodbc.connect(
r"Driver=Microsoft Access Driver (*.mdb, *.accdb);" +
r"Dbq=C:\Users\Ju\Desktop\Dark Summoner.accdb;")
cur = conn.cursor()
cur.execute("SELECT Number, ID, Name, Atk, Def, HP, BP, Species, Special FROM Impulse_AA");
while True:
row = cur.fetchone()
if row is None:
break
listadd = [row]
LIST = LIST+ listadd
GROUPS = max(((sum(map(lambda x:x[4]+x[5]+x[6],c)),c) for c in
itertools.combinations(LIST,5)),key=operator.itemgetter(0))[1]
我正在尝试存储可能的团队列表以供以后进行其他计算。不确定是否存储信息是最好的方法,或者每次重新计算是否更好。
但到目前为止,程序运行并且永远不会完成(或至少在 5-10 分钟后)。我目前的数据库中有 189 种生物,即 1,905,305,787 种组合。
编辑
创建所有可能的组的原因是需要考虑其他因素。我已经更新了 creativeList 以反映几个因素来举个例子。
BattlePower bonus = 10% atk and 10% def, all creatures have the same battle power
Type bonus = 15% atk and 15% def, all creatures have the same type
创建团队后,有 32 种不同的组合奖励可供检查。我认为创建列表然后检查它的组奖金比检查一个组并添加奖金并比较每组以查看哪个是最好的更省力。此外,一旦创建了列表并存储了所有最大统计数据,我将尝试将其导出为 Microsoft Access 文档,这样我只需在新生物出现时对其进行计算。
【问题讨论】:
【参考方案1】:作为单行:
>>> max(((sum(map(lambda x:x[2]+x[3],c)),c) for c in
itertools.combinations(creatureList,5)),key=operator.itemgetter(0))[1]
([1, 'Snake', 1000, 500],
[3, 'Turtle', 200, 2000],
[4, 'Cat', 1500, 700],
[5, 'Dog', 1700, 800],
[7, 'Badger', 2000, 1500])
itertools.combinations(creatureList,5)
为所有 5 元素生物组合返回一个迭代器。
(sum(map(lambda x:x[2]+x[3],c)),c)
是给定 5 元素组合的攻击/防御值之和与组合本身的元组。
max(...,key=...)
返回具有最大攻击/防御总和值的元组。
max(...)[1]
提取对应的组合。
更新
根据对问题的编辑和生物的数量 (189),有一种更好的方式来说明问题,从而导致更简单的解决方案。您有效地将每个生物的攻击和防御值相加,然后为 5 个生物的组合寻找这些值的最大总和。最大的总和将对应于具有最高个人攻击/防御总和的 5 个生物(因为总和是关联和可交换的)。
因此,您可以通过创建一个按攻击/防御总和排序的生物列表,然后选择列表末尾的 5 个生物(这比尝试所有可能的组合要快得多)来获得您正在寻找的结果:
>>> [x for x in sorted(creatureList,key=lambda x: x[2]+x[3])][-5:]
[[1, 'Snake', 1000, 500],
[3, 'Turtle', 200, 2000],
[4, 'Cat', 1500, 700],
[5, 'Dog', 1700, 800],
[7, 'Badger', 2000, 1500]]
这个解决方案的问题在于它没有考虑攻击/防御总和相等的生物。当可能有多个解决方案时,它只会给出一个解决方案。以下代码是一种处理方法:
result = list() # the desired list of 5 creature groups
base = list() # the prefix of all 5 creature groups
length = 5 # the number of creatures remaining to create a 5 creature list
for group in reversed([[x for x in g]
for k,g in itertools.groupby(
sorted(map(lambda x: x + [x[2]+x[3]],creatureList),
key=operator.itemgetter(4)),
key=operator.itemgetter(4))]):
grouplen = len(group)
if grouplen <= length:
base.extend(group)
length -= grouplen
elif length:
for c in itertools.combinations(group,length):
result.append(base + list(c))
break
鉴于这些生物:
[ [1, 'Snake', 1000, 500],
[2, 'Mouse', 500, 200],
[3, 'Turtle', 200, 2000],
[4, 'Cat', 1500, 700],
[5, 'Dog', 1700, 800],
[6, 'Bird', 100, 100],
[7, 'Badger', 2000, 1500],
[8, 'XXX', 500, 1000] ]
结果是:
[ [ [7, 'Badger', 2000, 1500, 3500],
[5, 'Dog', 1700, 800, 2500],
[3, 'Turtle', 200, 2000, 2200],
[4, 'Cat', 1500, 700, 2200],
[1, 'Snake', 1000, 500, 1500] ],
[ [7, 'Badger', 2000, 1500, 3500],
[5, 'Dog', 1700, 800, 2500],
[3, 'Turtle', 200, 2000, 2200],
[4, 'Cat', 1500, 700, 2200],
[8, 'XXX', 500, 1000, 1500] ] ]
附加字段是攻击/防御总和。如果需要,它很容易摆脱。但这是我留给你的练习。
【讨论】:
我使用了你的代码并且很确定我得到了它的工作。但是当我运行程序时它会继续运行。我让它运行超过 5 分钟,看看它是否只是因为组合的数量而需要时间,但不确定。还有什么建议吗?用我的代码更新了上面的评论。 用更好的问题陈述和相应的解决方案更新了答案。【参考方案2】:这称为Combinations,Python 对此有标准函数:itertools.combinations。
请记住,组合的数量是n!/(k!*(n-k!))
- 所以它增长很快。对于 100 个生物,将是 7500 万,对于 1000 个生物,将超过 8 万亿。使用迭代器,不要试图把它变成内存中的列表。
【讨论】:
好点。我刚刚算了一下,根据我目前可用的生物数量,它最终是 1,905,305,787 种组合。以上是关于如何从 access 中导入的数据创建一组列表?的主要内容,如果未能解决你的问题,请参考以下文章