【问题标题】:How to use python csv module for splitting double pipe delimited data如何使用 python csv 模块拆分双管道分隔的数据
【发布时间】:2011-06-15 02:35:17
【问题描述】:

我有如下数据:

"1234"||"abcd"||"a1s1"

我正在尝试使用 Python 的 csv 读写器进行读写。 由于 csv 模块的分隔符仅限于单个字符,有没有办法干净地检索数据?我无法删除空列,因为它是一个庞大的数据集,需要以时间限制的方式进行处理。任何想法都会有所帮助。

【问题讨论】:

  • 你说你不能放手然后删除空列。您尝试时速度过慢的原因是什么?
  • 问题应该表明我们是否可以从示例数据中进行概括。我在下面的回答假设“是”。

标签: python csv delimiter


【解决方案1】:

The docs 和实验证明只允许使用单字符分隔符。

由于cvs.reader 接受任何支持迭代器协议的对象,您可以使用生成器语法将||-s 替换为|-s,然后将此生成器提供给阅读器:

def read_this_funky_csv(source):
  # be sure to pass a source object that supports
  # iteration (e.g. a file object, or a list of csv text lines)
  return csv.reader((line.replace('||', '|') for line in source), delimiter='|')

此代码非常有效,因为它一次在一个 CSV 行上运行,前提是您的 CSV 源产生的行不超过您的可用 RAM :)

【讨论】:

  • 大概使用双管道分隔符的原因是因为给定值中可能存在单管道。
  • @Arafangion:是的。也许需要更精细的生成器表达式来缓解这个缺陷。
  • @Arafangion 只需将双管道分隔符替换为另一个值中不出现的分隔符(,;$%}^ø 或其他)。
  • @PavelRepin 一段很棒的代码!!!解决我的问题,我不知道为什么提问者没有将此标记为答案。
【解决方案2】:
>>> import csv
>>> reader = csv.reader(['"1234"||"abcd"||"a1s1"'], delimiter='|')
>>> for row in reader:
...     assert not ''.join(row[1::2])
...     row = row[0::2]
...     print row
...
['1234', 'abcd', 'a1s1']
>>>

【讨论】:

    【解决方案3】:

    不幸的是,分隔符在 C 中由一个字符表示。这意味着它不可能是 Python 中的单个字符以外的任何东西。好消息是可以忽略 null 值:

    reader = csv.reader(['"1234"||"abcd"||"a1s1"'], delimiter='|')
    #iterate through the reader.
    for x in reader:
        #you have to use a numeric range here to ensure that you eliminate the 
        #right things.
        for i in range(len(x)):
            #Odd indexes will be discarded.
            if i%2 == 0: x[i] #x[i] where i%2 == 0 represents the values you want.
    

    还有其他方法可以实现这一点(例如,可以编写一个函数),但这会为您提供所需的逻辑。

    【讨论】:

    • 你会如何处理:'1234||ab|cd||a1s1'?
    • @Arafangion 最初的例子不仅仅是用管道划定的,它是用管道和双引号划定的。这意味着 csv.reader 将忽略行中心的管道。
    【解决方案4】:

    如果您的数据字面上看起来像示例(字段从不包含“||”并且总是被引用),并且您可以容忍引号,或者愿意稍后将它们切掉,只需使用.split

    >>> '"1234"||"abcd"||"a1s1"'.split('||')
    ['"1234"', '"abcd"', '"a1s1"']
    >>> list(s[1:-1] for s in '"1234"||"abcd"||"a1s1"'.split('||'))
    ['1234', 'abcd', 'a1s1']
    

    仅当在字段中找到分隔符或删除字段周围的可选引号时才需要 csv

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多