我在字符串中接收这样的数据:
foo = """Port Mac Address group-addr vlan ver
s2p2 0100.5e00.0004 239.0.0.4 1 1
s2p0 0100.5e00.0005 239.0.0.8 1 1
s2p1 0100.5e00.0004 239.0.0.4 1 1"""
我希望将其格式化为表格。当数据进入表格时,我想要每个单独的一行,除非后者4是相同的(mac,group,vlan,ver)。如果发生这种情况,我希望数据在一行上并打印彼此旁边的两个端口
Vlan Group Type Version Port List
-----------------------------------------------------------------------
1 239.0.0.4 igmp v1 s2p1, s2p2
1 239.0.0.8 igmp v1 s2p0
我将数据解析为字典列表:
def parse_lines(lines):
headers = lines[0].split()
entries = []
for r in lines[1:]:
if not len(r): continue # skip blank lines
vals = r.split()
e = dict(zip(headers,vals))
entries.append(e)
return entries
def print_table():
print "%s %10s %10s %14s %15s" % ("Vlan", "Group", "Type", "Version", "Port List")
print "---------------------------------------------------------"
if foo is not None:
entries = foo.replace("Mac Address", "Mac-Address")
entries = parse_lines(entries.split("\n"))
这给我留下了一个字典列表,这是一个格式的例子:
[{'group-addr': '239.0.0.4', 'vlan': '1', 'ver': '1', 'Port': 's2p1', 'Mac-Address': '0100.5e00.0004'}, {'group-addr': '239.0.0.5', 'vlan': '1', 'ver': '1', 'Port': 's2p1', 'Mac-Address': '0100.5e00.0005'}]
在打印之前,我应该如何处理这些以进行比较和存储? 创建一个新词典?比较整个前一个字典的等价的非端口值,然后如果它们都是相同的测试端口并将值添加到新字典中?
答案 0 :(得分:2)
如果我理解正确,您可以执行以下操作。
对于您收到的每一行,获取除端口之外的所有值,并将它们作为元组中的元组键添加。
('239.0.0.4','0100.5e00.0004', '1', '1') = (group-addr, Mac-Address, vlan, ver)
当然,您可以选择最喜欢的订单,保留。
与元组键关联的值是设置端口。
最后,您将拥有许多键值对。把所有这些都放在字典里。
因此字典将如下所示:
{(group-addr, Mac-Address, vlan, ver): set(port1, port2), ...}
要添加新元素,您可以执行以下操作:
try:
dict[(group-addr, Mac-Address, vlan, ver)].add(port)
except KeyError:
dict[(group-addr, Mac-Address, vlan, ver)] = set(port)
我现在无法测试它,但我希望你能得到逻辑。
答案 1 :(得分:2)
使用Mac地址,group-addr,vlan和ver作为组合常用元素的键,您应该在最初创建dict时执行此操作,但这是使用您问题中的数据的示例:
foo = """Port Mac Address group-addr vlan ver
s2p2 0100.5e00.0004 239.0.0.4 1 1
s2p0 0100.5e00.0005 239.0.0.8 1 1
s2p1 0100.5e00.0004 239.0.0.4 1 1"""
from collections import defaultdict
d = defaultdict(set)
lines = foo.splitlines()
for line in lines[1:]:
prt,mc,gp,vl,vr = line.split()
d[(mc,gp,vl,vr)].add(prt)
print(d)
defaultdict(<type 'set'>, {('0100.5e00.0004', '239.0.0.4', '1', '1'): set(['s2p2', 's2p1']), ('0100.5e00.0005', '239.0.0.8', '1', '1'): set(['s2p0'])})
print "%s %10s %14s %15s" % ("Vlan", "Group", "Version", "Port List")
print "---------------------------------------------------------"
for mc, gp, vl, vr in d:
print("{:<10} {:<14} {:<15}".format(vl,gp,vr)) +",".join(d[mc, gp, vl, v])
Vlan Group Version Port List
---------------------------------------------------------
1 239.0.0.4 1 s2p2,s2p1
1 239.0.0.8 1 s2p0
答案 2 :(得分:1)
一个非常天真的解决方案:
from collections import defaultdict
def group_entries(entries):
grouped = defaultdict(list)
for entry in entries:
port = entry.pop("Port")
key = tuple(entry.items())
grouped[key].append(port)
results = []
for entry, ports in grouped.items():
entry = dict(entry)
entry["ports"] = ", ".join(ports)
results.append(entry)
return results
def print_table():
print "%s %10s %10s %14s %15s" % ("Vlan", "Group", "Type", "Version", "Port List")
print "---------------------------------------------------------"
if foo is not None:
entries = foo.replace("Mac Address", "Mac-Address")
entries = parse_lines(entries.split("\n"))
entries = group_entries(entries)
# etc
但是在较大的数据集上这可能效率很低。
答案 3 :(得分:1)
重要的是使用要保持相同的字段(mac,group,vlan和ver)为字典创建元组键。然后,创建一个变量来保存端口。我已经选择了一个列表 - 您可以像其他人建议的那样使用一个集合 - 当您打印到&#34; uniqify&#34;港口。我还没有对输出进行任何格式化 - 只需按照指南进行操作即可。我无法看到&#34;键入&#34;在决赛桌中来自 - 但我确信你可以适应这一点。
此外,您的决赛桌不包含MAC列。如果您不需要每个MAC地址一行,只需将其从字典键中删除
即可foo = """Port Mac Address group-addr vlan ver
s2p2 0100.5e00.0004 239.0.0.4 1 1
s2p0 0100.5e00.0005 239.0.0.8 1 1
s2p1 0100.5e00.0004 239.0.0.4 1 1"""
lines = foo.splitlines()
headers = lines[0]
machineDict={}
for line in lines[1:]:
prt,mac,grp,vl,vr = line.split()
try:
#try to add a new port to the entry with this key
machineDict[(mac,grp,vl,vr)].append(prt)
except KeyError:
#key error signals the dictionary doesn't contain that key
# so create an entry
machineDict[(mac,grp,vl,vr)] = [prt]
print "%s %10s %10s %14s %15s" % ("Vlan", "Group", "Type", "Version", "Port List")
print "---------------------------------------------------------"
for (mac,grp,vl,vr),portList in machineDict.items():
print "%s %10s %10s %14s %15s" % (vl,grp,"typeVar",vr,list(set(portList)))
注意list(set(portList))
结构只是&#34; unqified&#34;您的机器的端口列表。因为它们在您的输入数据中可能是唯一的 - 如果适合您,可以将其替换为portList
答案 4 :(得分:0)
根据Peter Bengtsson的Fastest way to uniqify a list in Python,两个表现最好的方法结果是将序列转换为一组 - 有序或正常。
那里有一个相当古老的Python版本的代码,所以我不会在这里粘贴它。相反,Does Python have an ordered set?给出了第一个选项的概述(第二个是内置类型)。
要成为集合的成员,您的元素必须是可清除的。所以,你需要例如使用namedtuple
而不是字典来存储记录。