1

我有一个列表字典,如下所示:

{'banana': [1,2],
 'monkey': [5],
 'cow': [1,5,0],
 ...}

我想编写一个包含一个数字和单词的csv,如下所示:

1 | banana
2 | banana
5 | monkey
1 | cow
5 | cow
0 | cow
...

与 | 作为分隔符。

我尝试将其转换为元组列表,并将其编写如下:

for k, v in dic.items():
    for ID in v: 
        rv.append((ID, k))

with open(index_filename,'wb') as out:
    csv_out=csv.writer(out, delimiter='|')
    csv_out.writerow(['identifier','descriptor'])
    for row in rv:
        csv_out.writerow(row)

但跑了这个错误:

a bytes-like object is required, not 'str'

有没有比转换为元组更有效的方法,如果没有,我的代码有什么问题?

谢谢。

4

2 回答 2

0

如果你想让你的代码更高效,重要的是,你要说明你想让它更有效率的地方。除了糟糕的解决方案之外,在合理的解决方案中,通常还需要在空间(内存)和时间(循环、函数调用)之间进行权衡。

除了效率之外,您还应该考虑可读性和可维护性。在进行任何类型的优化之前。

Python 中的 dicts 之类的元组非常高效,因为它们在内部到处都在使用。Python 中的大多数函数调用都涉及在底层创建元组(用于位置参数)。

至于您的具体示例,您可以使用生成器表达式来避免临时列表:

entries = ((k, v) for k, l in dic.items() for v in l)

您仍然有中间元组,但它们是在您迭代字典项时动态计算的。此解决方案比显式列表更节省内存,尤其是在您有很多条目的情况下。

您也可以将嵌套循环直接放入 with 主体中:

with open(index_filename,'wb') as out:
    csv_out=csv.writer(out, delimiter='|')
    csv_out.writerow(['identifier','descriptor'])
    for k, v in dic.items():
        for ID in v: 
            csv_out.writerow((k, ID))

为了避免对 的重复函数调用writerow,您还可以使用writerows,这可能会更快。

with open(index_filename,'wb') as out:
    csv_out=csv.writer(out, delimiter='|')
    csv_out.writerow(['identifier','descriptor'])
    csv_out.writerows((k, v) for k, l in dic.items() for v in l)

如果你真的对哪种方法最快感兴趣,可以使用 Python 的timeit模块进行测量。

于 2018-01-14T20:24:18.400 回答
0

您正在以二进制/字节模式打开文件,该模式由“wb”中的“b”指定。这是很多人在python2时代做的事情,当时“str”和“bytes”是同一个东西,所以很多老书还是这样教的。

如果以字节模式打开文件,则必须向其中写入字节,而不是字符串。str可以使用以下方法将A转换为字节str.encode()

f.write(some_str_variable.encode()

但是,您可能想要的是不要以字节模式打开文件。

with open(index_filename, 'w') as out:
    ...
于 2018-01-14T20:03:59.543 回答