【问题标题】:python find and match exact stringpython查找并匹配确切的字符串
【发布时间】:2014-03-19 14:12:54
【问题描述】:

如何将.csv 文件中的列中的字符串与定义的数据类型列表进行匹配?

数据类型列表为:

Datatype = ["M", "B", "E", "A", "DF", "DW", "DL", "DT", "XTEXT", "MDEDATA"]

我想使用与列匹配的数据类型在字典中查找值。

什么有效

当我的代码在输入中找到类似DW1 的内容时(请参阅下面的示例),它会将DW:5 写入输出文件,当它找到DT34 时,它会写入DT:7。这很好用。

什么不起作用

但问题是,每当我的代码遇到XTEXT 时,它首先将其匹配到E: 2(因为E 存在于XTEXT 中)然后然后 匹配到XTEXT: 4105下一行。结果,输出文件中的对应行包含2 而不是4105MDEDATA 也发生了类似的事情,解析为 A:3

我尝试使用正则表达式从输入文件的相关列中删除数字(此行在上面的代码中被注释掉),如下所示:

if (Datatype[n] == re.sub('[1234567890\n]', '', line.split(";")[1])):
    # ...

但这会在遇到像X256DATA 这样的字符串时导致问题。

另一个问题是当前生成的输出文件在第一列中显示abc;DW1,在第二列中显示5,但我希望在第一列中显示abc,在第二列中显示DW1,在第二列中显示@第三栏987654342@!

我该如何解决这些问题?任何帮助表示赞赏。


CSV 示例

输入:

1 abc DW1  
2 uz5 XTEXT

当前输出:

1 abc DW1    5
2 uz5 XTEXT  4105

TXT 示例

输入:

abc;DW1\n  
uz5;XTEXT\n

当前输出:

abc;DW1,5\n  
uz5;XTEXT,4105\n    

期望的输出

abc;DW1;5\n  
uz5;XTEXT;4105\n

【问题讨论】:

  • 不确定我是否完全理解您要执行的操作。您能否提供一些示例输入(即您正在解析的 CSV 文件的摘录)以及您用于将其转换为 dict1 / dict2 的代码?
  • 如何查询字典?
  • @vinu 感谢您添加代码。但是示例输入数据呢?如果你能提供一条线就太好了……
  • @vinu 太棒了!现在只需在输出文件中添加您希望这两行看起来像的内容。我知道您在文本中描述它,但是看到输入和 desired 输出彼此相邻将使我们更接近找到解决方案。 (我要求这样做的另一个原因是我觉得您的代码可能会大大缩短,并且仍然可以做您想做的事情。)
  • @vinu 好的,我现在会尝试在答案中解决这个问题。

标签: python string csv string-matching export-to-csv


【解决方案1】:

普通字典查找与键完全匹配。如果您获得多个匹配项,则您正在做其他事情。

>>> dict1 = {"M":1, "E":2, "A":3, "DF":4, "DW":5, "DL":6, "DT":7, "B":10, "XTEXT":4105, "MDEDATA":4110}
>>> dict1["XTEXT"]
4105

现在从更新的问题中,我看到您并不是真的在寻找精确匹配,因为文件中的 DW1 应该与 Datatype 中的 DW 匹配。如果要检查字符串的开头是否匹配,请使用str.startswith

>>> "DW1".startswith("DW")
True

请注意,您必须在M 之前检查MDEDATA,以避免错误匹配。更一般地,在较短的匹配之前检查较长的匹配。

【讨论】:

    【解决方案2】:

    好的,这是一个基于您的代码的解决方案,它应该适用于您的 .txt 文件格式:

    import csv
    
    # Define data_type / dict1 / dict2:
    
    data_type = [
        "M", "E", "B", "A", "DF", "DW", "DL", "DT", "PF", "PW", "PL", "PT",
        "XTEXT", "MDEDATA", "X8DATA", "X16DATA", "X32DATA", "X64DATA",
        "X128DATA", "X256DATA", "X512DATA", "X1024DATA", "X2048DATA",
        "X4096DATA", "X8912DATA"]
    
    dict1 = {
        "M": 1, "E": 2, "A": 3, "DF": 4, "DW": 5, "DL": 6, "DT": 7, "PF": 8,
        "PW": 9, "B": 10, "PL": 11, "PT": 12, "XTEXT": 4105, "MDEDATA": 4110,
        "X8DATA": 10000, "X16DATA": 10001, "X32DATA": 10002, "X64DATA": 10003,
        "X128DATA": 10004, "X256DATA": 10005, "X512DATA": 10006,
        "X1024DATA": 10007, "X2048DATA": 10008, "X4096DATA": 10009,
        "X8912DATA": 10010}
    
    dict2 = {
        "M": "B", "E": "B", "A": "B", "DF": ">f","PF": ">f", "DW": ">h",
        "PW": ">h", "DL": ">l", "PL": ">l", "DT": "String", "PT": "String",
        "B": "B", "XTEXT": "XTEXT", "MDEDATA": "MDEDATA", "X8DATA": "X8DATA",
        "X16DATA": "X16DATA", "X32DATA": "X32DATA", "X64DATA": "X64DATA",
        "X128DATA": "X128DATA", "X256DATA": "X256DATA", "X512DATA": "X512DATA",
        "X1024DATA": "X1024DATA", "X2048DATA": "X2048DATA",
        "X4096DATA": "X4096DATA", "X8912DATA": "X8912DATA"}
    
    # Obtain writer for output file:
    
    source = 'GSV.txt'
    dest = open('GSV_copy.txt', 'w')
    
    # Process data:
    
    import re
    
    source_lines = open(source).readlines()
    for line in source_lines:
        x = line.split(';')[1]
        icon_lletter = ''
        icon_lnummer = 0
        python_letter = ''
        for t in data_type:
            if x.startswith(t): # Alternative using re: "if re.match(t, x)"
                icon_lletter = t
                break
        if (icon_lletter not in dict1):
            print "Entry (%s) in Dictionary1 is not available" % (icon_lletter)
        else:
            icon_lnummer = dict1[icon_lletter]
        if (icon_lletter not in dict2):
            print "Entry (%s) in Dictionary2 is not available" % (icon_lletter)
        else:
            python_letter = dict2[icon_lletter]
            print "Converted the GVR datatype to python datatype is %s : %s : %s" \
                % (icon_lletter, python_letter, icon_lnummer)
            # Write line to output file:
            dest.write(';'.join([line.strip('\n'), str(icon_lnummer) + '\n']))
    
    dest.close()
    

    请注意:

    • 通过此解决方案,我正在尝试解决您的问题,同时保持接近您的原始实施。有多种实现目标的方法可能更 Pythonic / 高效 / DRY。

    • 由于您的输入和输出文件的列数不同并且格式不同,您最终会希望将代码转换为一个(一组)函数来获取不同(文件类型和要检查的列)作为参数。


    编辑:

    在处理这个问题时,我注意到dest 中的输出有点乱码。 (我之前还没有做到这一点:))我已经更改了代码以产生您现在想要的确切输出。


    另一个编辑(基于 cmets 中的讨论):

    关于将输入文件中的数据类型与定义的data_types 列表进行匹配的主题:如果输入文件中的DTs 始终包含您不想考虑的数字开头或结尾,你可以使用

    re.sub('^[0-9]+', '', x)
    

    re.sub('[0-9]+$', '', x)
    

    删除它们。

    【讨论】:

    • 我正在使用 python 2.7.... 它抛出错误为 --->if t.starts_with(x): AttributeError: 'str' object has no attribute 'starts_with'
    • @vinu 谢谢,这是一个错字。应该是t.startswith(x)编辑:已修复。
    • 好的,在字典中找不到任何条目!
    • @vinu 你是在.txt 文件上运行它吗?我还没有在我的答案中更改sourcedest 文件的名称......这样做并让我知道这是否会改变任何内容。如果没有,请尝试在 break 语句之前打印出 t 以查看发生了什么。
    • @vinu 在 break 语句之前打印 t 会得到什么?它是不是看起来应该在dict1/dict2 中的键?
    【解决方案3】:

    根据itsjeyd的建议,

    re.sub('^[0-9]+', '', x) or re.sub('[0-9]+$', '', x) does the trick!
    

    【讨论】:

    • 我很高兴我的建议对您有所帮助:) 我将它们添加到我的原始答案中。由于它现在包含您解决问题所需的所有信息,如果您能接受它(通过单击它旁边的复选标记),那就太好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多