我正在编写一个查看我的库存的脚本,将其与所有可能库存项目的主列表进行比较,并告诉我我缺少哪些项目。我的目标是.csv文件,其中第一列包含唯一键整数,然后剩下的几列将包含与该键相关的数据。例如,我的最终目标.csv文件的三行片段可能如下所示:
100001,apple,fruit,medium,12,red
100002,carrot,vegetable,medium,10,orange
100005,radish,vegetable,small,10,red
这方面的数据来自几个来源。 1,对API服务器的查询为我提供了库存中物品的键列表。 2,我在一个.csv文件中读入一个dict,它匹配所有可能键的项目名称。此.csv文件的前5行的片段可能如下所示:
100001,apple
100002,carrot
100003,pear
100004,banana
100005,radish
请注意我的库存列表中的任何键都可以在这两列.csv文件中找到,该文件提供所有键及其相应的项目名称,此列表减去我手头的库存会产生我正在寻找的内容(这是库存我需要得到。)
到目前为止,我可以获得一个.csv文件,其中只包含我在库存中没有的项目的键和项目名称。像这样提供库存清单:
100003,100004
我生成的.csv文件的片段如下所示:
100001,apple
100002,carrot
100005,radish
这意味着我在库存中有梨和香蕉(因此它们不在此.csv文件中。)
为了得到这个,我有一个函数来获得一个项目名称,当给出一个如下所示的项目ID:
def getNames(id_to_name, ids):
return [id_to_name[id] for id in ids]
然后是一个函数,它从我的库存服务器API调用中给出一个键列表作为整数,返回一个列表,我运行这个函数:
invlist = ServerApiCallFunction(AppropriateInfo)
第三个函数将此invlist作为其输入并返回键的dict(项id)和我没有的项的名称。它还将此dict的信息写入.csv文件。我使用set1 - set2方法来做到这一点。它看起来像这样:
def InventoryNumbers(inventory):
with open(csvfile,'w') as c:
c.write('InvName' + ',InvID' + '\n')
missinginvnames = []
with open("KeyAndItemNameTwoColumns.csv","rb") as fp:
reader = csv.reader(fp, skipinitialspace=True)
fp.readline() # skip header
invidsandnames = {int(id): str.upper(name) for id, name in reader}
invids = set(invidsandnames.keys())
invnames = set(invidsandnames.values())
invonhandset = set(inventory)
missinginvidsset = invids - invonhandset
missinginvids = list(missinginvidsset)
missinginvnames = getNames(invidsandnames, missinginvids)
missinginvnameswithids = dict(zip(missinginvnames, missinginvids))
print missinginvnameswithids
with open(csvfile,'a') as c:
for invname, invid in missinginvnameswithids.iteritems():
c.write(invname + ',' + str(invid) + '\n')
return missinginvnameswithids
然后我会这样称呼:
InventoryNumbers(invlist)
有了这个解释,现在我的问题在这里。我想通过添加其他列来扩展此输出.csv文件中的数据。这个数据将来自另一个.csv文件,其片段如下所示:
100001,fruit,medium,12,red
100002,vegetable,medium,10,orange
100003,fruit,medium,14,green
100004,fruit,medium,12,yellow
100005,vegetable,small,10,red
请注意这不包含项目名称(所以我必须从另一个只有两列密钥和项目名称的.csv文件中提取它)但它确实使用相同的密钥。我正在寻找一种方法来引入这些额外的信息,以便我的最终.csv文件不会只告诉我我没有库存的物品的钥匙(物品ID)和物品名称,但它也有类型,大小,数量和颜色的列。
我看过的一个选项是来自收藏品的defaultdict件,但我不确定这是否是我想要做的最佳方式。如果我确实使用了这种方法,我不确定我是如何调用它来实现我想要的结果的。如果其他方法更容易,我当然也愿意尝试。
我如何获取我在库存中没有的项目的密钥和相应项目名称,并以这样的方式添加这些额外信息,以便将其全部输出到.csv文件?
编辑:当我输入它时,我发现我可以通过创建一个新的单个.csv文件来使自己更容易,该文件将在表单键,项目名称,类型,大小,数量,颜色中具有日期(基本上只是将项目名称的列复制到已经拥有每个密钥的其他信息的.csv中。)这样我只需要从一个.csv文件中绘制而不是从两个.csv文件中绘制。即使我这样做了,我怎样才能根据那些不在库存中的商品的密钥来制作我想要的.csv文件?答案:我发布了另一个问题here,关于如何实现我接受的解决方案(因为我的dict值是字符串而不是设置开始时给我一个值错误)我最终决定我想要一个列表而不是一个集合(以保留订单。)我最后还将带有项目名称的列添加到我的.csv文件中,该文件包含所有其他数据,因此我只需要从一个.csv文件中绘制。也就是说,这部分代码现在是这样的:
MyDict = {}
infile = open('FileWithAllTheData.csv', 'r')
for line in infile.readlines():
spl_line = line.split(',')
if int(spl_line[0]) in missinginvids: #note that this is the list I was using as the keys for my dict which I was zipping together with a corresponding list of item names to make my dict before.
MyDict.setdefault(int(spl_line[0]), list()).append(spl_line[1:])
print MyDict
答案 0 :(得分:1)
听起来你需要的是一个dict映射ints to sets,即
MyDict = {100001: set([apple]), 100002: set([carrot])}
您可以添加更新:
MyDict[100001].update([fruit])
会给你:{100001: set([apple, fruit]), 100002: set([carrot])}
此外,如果您有胡萝卜属性列表... [vegetable,orange]
你可以说MyDict[100002].update([vegetable, orange])
并获取:{100001: set([apple, fruit]), 100002: set([carrot, vegetable, orange])}
这会回答你的问题吗?
编辑:
读入CSV ...
infile = open('MyFile.csv', 'r')
for line in infile.readlines():
spl_line = line.split(',')
if int(spl_line[0]) in MyDict.keys():
MyDict[spl_line[0]].update(spl_line[1:])
答案 1 :(得分:1)
这不是问题的答案,但这是一种简化当前代码的可行方法。
此:
invids = set(invidsandnames.keys())
invnames = set(invidsandnames.values())
invonhandset = set(inventory)
missinginvidsset = invids - invonhandset
missinginvids = list(missinginvidsset)
missinginvnames = getNames(invidsandnames, missinginvids)
missinginvnameswithids = dict(zip(missinginvnames, missinginvids))
可替换为:
invonhandset = set(inventory)
missinginvnameswithids = {k: v for k, v in invidsandnames.iteritems() if k in in inventory}
或者:
invonhandset = set(inventory)
for key in invidsandnames.keys():
if key not in invonhandset:
del invidsandnames[key]
missinginvnameswithids = invidsandnames
答案 2 :(得分:0)
您是否考虑过制作一个临时RDB(python已经sqlite support出现)并且对于合理数量的项目,我认为您不会遇到性能问题。
我会将每个CSV文件和web-api的结果转换成表格(每个数据源一个表格)。然后,您可以使用某些SQL查询+连接执行您想要执行的所有操作。获得所需数据后,可以将其转储回CSV。