【问题标题】:Replace item in string formatted as csv line替换格式为 csv 行的字符串中的项目
【发布时间】:2018-07-10 11:25:27
【问题描述】:

目标是以优雅的方式将csv_line 的第二个字段替换为new_item。这个问题与 Rawing 列出的主题不同,因为我们在这里使用不同的数据结构,尽管我们可以使用其他主题来获得启发。

# Please assume that csv_line has not been imported from a file.
csv_line = 'unknown_item1,unknown_old_item2,unknown_item3'
new_item = 'unknown_new_item2'
goal = 'unknown_item1,unknown_new_item2,unknown_item3'

# Works but error prone. Non-replaced items could be inadvertently swapped.
# In addition, not convenient if string has many fields.
item1, item2, item3 = csv_line.split(',')
result = ','.join([item1, new_item, item3])
print(result)  # unknown_item1,unknown_new_item2,unknown_item3

# Less error prone but ugly.
result_list = []
new_item_idx = 1
for i, item in enumerate(csv_line.split(',')):
    result_list += [item] if i != new_item_idx else [new_item]
result = ','.join(result_list)
print(result)  # unknown_item1,unknown_new_item2,unknown_item3

# Ideal (not-error prone) but not working.
csv_line.split(',')[1] = new_item
print(csv_line)  # unknown_item1,unknown_old_item2,unknown_item3

【问题讨论】:

标签: python string csv replace


【解决方案1】:

可以使用 Python 的 CSV 库通过使用 io.StringIO() 对象来替换第二项。这表现得像文件,但可以作为字符串读取:

import csv
import io

csv_line = 'unknown_item1,unknown_old_item2,unknown_item3'
new_item = 'unknown_new_item2'

row = next(csv.reader(io.StringIO(csv_line)))
row[1] = new_item
output = io.StringIO()
csv.writer(output).writerow(row)
goal = output.getvalue()

print(goal)

这会将goal 显示为:

unknown_item1,unknown_new_item2,unknown_item3

【讨论】:

  • 考虑到它比使用split(',') 涉及更多逻辑,接受这个答案的理由是什么?
  • 因为它能够正确处理完整的 CSV 条目,例如 abc,"hello, world",def
【解决方案2】:

这似乎是最pythonic:

csv_line = 'unknown_item1,old_item2,unknown_item3'
old_index = 1
new_item = 'new_item2'
goal = 'unknown_item1,new_item2,unknown_item3'

items = csv_line.split(',')
items[old_index] = new_item

print(','.join(items))
print(goal)

输出:

unknown_item1,new_item2,unknown_item3
unknown_item1,new_item2,unknown_item3

【讨论】:

  • 你应该使用 csv 模块而不是用逗号分割。
  • @Rawing 我不清楚csv 模块如何拆分逗号分隔的字符串
  • 开始的假设是old_item2是未知的,所以我们不能使用!=。
  • 好的,我将用替换第二个字段的代码更新我的答案。
  • 这个想法是使用 csv 阅读器来读取输入,使其不再是字符串。我们不知道 OP 从哪里得到这个字符串,但很可能它是从文件或类似文件的对象中读取的。将其包装在 csv 阅读器中是微不足道的。
【解决方案3】:

在csv_line.split(',')[1] = new_item 行中,您根本不更改 csv_line 变量。您需要先将使用 .split() 创建的新列表分配给变量,然后才能更改其中的元素:

new_csv = csv_line.split(',')
new_csv[1] = new_item

print(','.join(new_csv))

【讨论】:

  • 你应该使用 csv 模块而不是用逗号分割。
  • 你说得对,但是 csv_line 是作为字符串给出的,所以在这种情况下涉及 csv 库是没有意义的。
  • 包含一个使您的代码正常工作的库绝不是毫无意义的。此外,我们不知道 OP 从哪里获取数据。如果输入是从任何类似文件的对象中读取的,则将其包装在 csv 阅读器中是微不足道的。
  • @Tynan 我接受了 talz 的回答,因为他的速度快了几秒钟,而且答案都是一样的。
【解决方案4】:
l = csv_line.split(',')
l[1] = new_item
csv_line = ','.join(l)

【讨论】:

  • 你应该使用 csv 模块而不是用逗号分割。
  • @Rawing, csv 模块用于“CSV 文件读写”。问题是关于“格式化为 csv 行的字符串”。提问者可能只是用它来表示“逗号分隔的一行字符串”。我们甚至不知道是否涉及任何文件......
  • csv 数据不仅仅是用逗号分隔的文本,所以如果你只是用逗号分隔,你的程序是不正确的。除非输入字符串突然出现,否则几乎可以肯定它是从可以包装在 csv 阅读器中的文件(或其他类似文件的对象)中读取的。如果不是,您可以将字符串包装在 StringIO 对象中。为换取正常运行的程序而付出的小代价。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-21
相关资源
最近更新 更多