我有一个包含卡车配置的长文本文件。在每一行中,卡车的一些属性被列为字符串。每个属性在字符串中都有自己的固定宽度空间,例如:
2 chracters = number of axles
2 characters = weight of the first axle
2 characters = weight of the second axle
...
2 characters = weight of the last axle
2 characters = length of the first axle spacing (spacing means distance between axles)
2 characters = length of the second axle spacing
...
2 characters = length of the last axle spacing
举个例子:
031028331004
指的是:
number of axles = 3
first axle weight = 10
second axle weight = 28
third axle weight = 33
first spacing = 10
second spacing = 4
现在,您对我的文件结构有了一个了解,这是我的问题:我想将这些卡车分组在单独的列表中,并根据轴间距命名列表。假设我使用布尔类型的方法,如果间距小于6,则布尔值为1,如果大于6,则布尔值为0.为了澄清,三轴卡车中的可能结果变为:< / p>
00 #Both spacings > 6
10 #First spacing < 6, second > 6
01 #First spacing > 6, second < 6
11 #Both spacings < 6
现在,正如您所看到的,3轴卡车没有太多结果。但是,如果我有一个12轴卡车,“可能”组合的数量会变得混乱。事实是,实际上你不会看到12轴卡车中轴间距的所有“可能”组合。有一些组合(我不知道哪些组合,但要弄明白是我的目标),其数量远远低于“可能”的组合数量。
我希望代码能够创建列表并使用定义上面提到的属性的字符串填充它们如果只有这样的组合存在。我想也许我应该用变量名创建列表,例如:
truck_0300[]
truck_0301[]
truck_0310[]
truck_0311[]
即时。但是,从我在SF和其他来源中读到的内容来看,强烈建议不要这样做。你会如何使用字典概念?据我所知,词典就像是二维数组,有一个键(在我的例子中键会像truck_0300,truck_0301等)和值对(在我的情况下,值也可能是包含实际字符串的列表)属于相应的卡车类型),但我无法弄清楚如何创建该字典,并用变量键和值填充它。
欢迎任何见解! 非常感谢!
答案 0 :(得分:5)
你绝对是正确的,尝试在范围内创建“动态变量”几乎总是一个坏主意。字典通常是随着时间的推移建立一组对象并引用它们的答案......
我不完全了解您的应用程序和格式,但一般来说,定义和使用您的字典时,它看起来像这样:
trucks = {}
trucks['0300'] = ['a']
trucks['0300'].append('c')
trucks['0300'].extend(['c','d'])
aTruck = trucks['0300']
现在因为每个字符串都应该是你的字符串列表,你可能只想使用defaultdict,并告诉它使用列表作为非存在键的默认值:
from collections import defaultdict
trucks = defaultdict(list)
trucks['0300']
# []
请注意,即使它是一个不包含任何条目的全新字典,“truck_0300”键仍会返回一个新列表。这意味着您无需检查密钥。只需追加:
trucks = defaultdict(list)
trucks['0300'].append('a')
defaultdict
可能就是您想要的,因为您根本不需要预先定义键。当你准备好它时它就在那里。
获取最大值的密钥
根据您的评论,以下是如何使用字典的最大值获取密钥的示例。这非常简单,因为您只需使用max
并定义它应如何确定用于比较的密钥:
d = {'a':10, 'b':5, 'c':50}
print max(d.iteritems(), key=lambda (k,v): v)
# ('c', 50)
d['c'] = 1
print max(d.iteritems(), key=lambda (k,v): v)
# ('a', 10)
您所要做的就是定义如何生成比较密钥。在这种情况下,我只是告诉它将值作为关键。对于这样的关键函数,你只是告诉它从对象中提取索引或属性,你可以通过使用operator
模块使其更有效,这样键函数在C中而不在python中作为一个lambda:
from operator import itemgetter
...
print max(d.iteritems(), key=itemgetter(1))
#('c', 50)
itemgetter
创建一个新的callable,它将从循环传入的元组中提取第二个项目。
现在假设每个值实际上都是一个列表(类似于您的结构)。我们将它设为一个数字列表,并且您希望找到具有最大总数的列表的键:
d = {'a': range(1,5), 'b': range(2,4), 'c': range(5,7)}
print max(d.iteritems(), key=lambda (k,v): sum(v))
# ('c', [5, 6])
答案 1 :(得分:1)
如果密钥数超过10,000,则此方法不可行。否则定义一个字典d = {}并在你的行上循环:
key = line[:4]
if not key in d.keys():
d[key] = []
d[key] += [somevalue]
我希望这会有所帮助。
答案 2 :(得分:0)
这是从字符串到输出的完整解决方案:
from collections import namedtuple, defaultdict
# lightweight class
Truck = namedtuple('Truck', 'weights spacings')
def parse_truck(s):
# convert to array of numbers
numbers = [int(''.join(t)) for t in zip(s[::2], s[1::2])]
# check length
n = numbers[0]
assert n * 2 == len(numbers)
numbers = numbers[1:]
return Truck(numbers[:n], numbers[n:])
trucks = [
parse_truck("031028331004"),
...
]
# dictionary where every key contains a list by default
trucks_by_spacing = defaultdict(list)
for truck in trucks:
# (True, False) instead of '10'
key = tuple(space > 6 for space in truck.spacings)
trucks_by_spacing[key].append(truck)
print trucks_by_spacing
print trucks_by_spacing[True, False]