查找字符串

时间:2017-08-02 17:40:32

标签: python csv

我看到很多在字符串中查找字符串或在列表中查找字符串的示例,但是如何在字符串中查找列表。例如,我有一个包含数据列的csv文件,最后一列是字符串,有时它是一个列表。以下是仅显示最后3列的数据子集。

TRUE, 93877, S26476961
TRUE, 93878, ['S26489167', 'S26492524']
FALSE, 93879, S26476962
FALSE, 93880, ['S26489168', 'S26492527', 'S26492528']

起初我试图用逗号解析csv文件的每一行,但它解析列表中的逗号(创建额外的列)。我只是希望列表被识别为单个数据,因此我可以将其作为'n'项列表使用。 @TemporalWolf的评论很有帮助,因为如果我使用csv模块(特别是csv.reader)就是这样......

reader = csv.reader(inFile)
for row in reader:
    print(row)

它将列表保留在一列中。现在的问题仍然是它只是一个字符串。换句话说,row[n][0]会返回左括号([),但我想将其添加到列表中。

3 个答案:

答案 0 :(得分:4)

这取决于引用列表元素的'字符。使用此信息时,它仅使用正则表达式:

在未跟随或前面的逗号上分割逗号
import re
import pandas as pd
import io


text = """TRUE, 93877, S26476961
TRUE, 93878, ['S26489167', 'S26492524']
FALSE, 93879, S26476962
FALSE, 93880, ['S26489168', 'S26492527', 'S26492528']"""

with io.StringIO(text) as f:
    for line in f:
        print(re.split("(?<!'), (?!')", line.strip()))


# ['TRUE', '93877', 'S26476961']
# ['TRUE', '93878', "['S26489167', 'S26492524']"]
# ['FALSE', '93879', 'S26476962']
# ['FALSE', '93880', "['S26489168', 'S26492527', 'S26492528']"]

# Or with pandas

with io.StringIO(text) as f:
    print(pd.read_csv(f,
                  header=None,
                  sep="(?<!'), (?!')",
                  engine='python'))

#        0      1                                        2
# 0   True  93877                                S26476961
# 1   True  93878               ['S26489167', 'S26492524']
# 2  False  93879                                S26476962
# 3  False  93880  ['S26489168', 'S26492527', 'S26492528']

编辑:

如果您使用的是python2,则需要将文本转换为unicode(通过在文本前放置字符u)才能使用io.StringIO

import re
import pandas as pd
import io


text = u"""TRUE, 93877, S26476961
TRUE, 93878, ['S26489167', 'S26492524']
FALSE, 93879, S26476962
FALSE, 93880, ['S26489168', 'S26492527', 'S26492528']"""

with io.StringIO(text) as f:
    for line in f:
        print(re.split("(?<!'), (?!')", line.strip()))


# ['TRUE', '93877', 'S26476961']
# ['TRUE', '93878', "['S26489167', 'S26492524']"]
# ['FALSE', '93879', 'S26476962']
# ['FALSE', '93880', "['S26489168', 'S26492527', 'S26492528']"]

# Or with pandas

with io.StringIO(text) as f:
    print(pd.read_csv(f,
                  header=None,
                  sep="(?<!'), (?!')",
                  engine='python'))

#        0      1                                        2
# 0   True  93877                                S26476961
# 1   True  93878               ['S26489167', 'S26492524']
# 2  False  93879                                S26476962
# 3  False  93880  ['S26489168', 'S26492527', 'S26492528']

编辑2:

如果您不希望依赖引号字符'的存在,您可以尝试以下操作:

import ast
import re


with io.StringIO(text) as f:
    for line in f:
        parts = re.split(", (?=\[)", line.strip())
        line = []
        for part in parts:
            if all(char in part for char in ('[]')):
                line.append(ast.literal_eval(part))
            else:
                line += part.split(", ")
        print(line)

您拆分位于左方括号前面的逗号,然后按如下方式检查结果:

  1. 检查从拆分操作生成的列表的每个元素是否都有方括号。如果是,则将其转换为list ast.literal_eval对象,并将其添加到最终输出列表中。
  2. 否则,请在逗号上拆分并将随后的列表添加到最终输出列表中。
  3. 这应该与上述解决方案相同。

    我希望这会有所帮助。

答案 1 :(得分:2)

这是一个有趣的解决方案:在逗号上拆分每一行,并尝试将每个部分解析为Python代码。如果它无效,这意味着我们不包括整个列表:

import ast

def get_columns(line):
    def valid(code):
        try:
            ast.parse(code.strip())
        except SyntaxError:
            return False
        return True
    sections = line.split(',')
    columns = []
    for i, section in enumerate(sections):
        if i == len(sections) - 1 or valid(section):
            columns.append(section)
        else:
            sections[i + 1] = ','.join([section, sections[i + 1]])
    return columns

with open(inFile) as f:
    for line in f:
        for column in get_columns(line):
            print(column)

由于这不涉及您的确切情况的正则表达式,这是非常一般的。还要注意,因为没有#34;代码&#34;在您的数据文件中进行评估以执行测试,这是完全安全的。

适用于Python 2和3。

答案 2 :(得分:0)

这是相反的方法。它通过检查行的项目中的前导csv.reader和尾随[来查找]返回的数据中的列表。

import csv 

def find_lists(row):
    sublist = []
    for item in row:
        if not sublist:
            if item.startswith('['):
                if item.endswith(']'):
                    yield [item[1:-1]]
                else:
                    sublist.append(item[1:])
            else:
                yield item
        else:
            if item.endswith(']'):
                sublist.append(item[:-1])
                yield sublist
                sublist = []
            else:
                sublist.append(item)
    for item in sublist:
        yield item

with open('test.csv') as infile:
    reader = csv.reader(infile, skipinitialspace=True)
    for row in reader:
        print(list(find_lists(row)))