2017-07-31 100 views
1

我有两个类型的字符串,类似于下面如何解析自定义字符串并从该字符串创建字典?

string1 = 'ID=mRNA42;Parent=gene19;integrity=0.95;foo=bar' 
string2 = 'transcript_id "g3.t1"; gene_id "g3";' 

我试图创建将根据字符串拿上面的字符串作为输入,并返回字典的功能。

为STRING1字典,结构就像是

attributes = { 
    'ID': 'mrna42', 
    'Parent': 'gene19', 
    'integrity': '0.95', 
    'foo': 'bar', 
} 

,为字符串2

attributes = { 
    'transcript_id': 'g3.t1', 
    'gene_id': 'g3', 
} 

我尝试:

def parse_single_feature_line(attributestring): 

    attributes = dict() 
    for keyvaluepair in attributestring.split(';'): 
     for key, value in keyvaluepair.split('='): 
      attributes[key] = value 
    return attributes 

我需要帮助建立功能。

+0

检查我的简化的答案的答案...我用你现有的函数与正则表达式 –

回答

1

试试这个

string1 = 'ID=mRNA42;Parent=gene19;integrity=0.95;foo=bar' 
string2 = 'transcript_id "g3.t1"; gene_id "g3";' 

def str2dict(s): 
    result={} 
    for i in s.split(";"): 
      ele=i.strip() 
      if not ele:continue 
      if "=" in i: 
        key,val=ele.split("=") 
      else: 
        key,val=ele.split() 
      result[key]=val.strip('"') 
    return result 

str2dict(string1) 
str2dict(string2) 
+0

我正在运行脚本时得到“** ValueError:没有足够的值解压(预期2,得到0)**”。所以你可以请检查一下。 – Arijit

+1

这来自尾随的“;”在string2结尾处产生一个额外的空字符串 –

+0

更新上面的代码请检查。 –

1

您可以使用字典理解!

>>> string1 
'ID=mRNA42;Parent=gene19;integrity=0.95;foo=bar' 
>>> string2 
'transcript_id "g3.t1"; gene_id "g3";' 
>>> {each.split('=')[0]:each.split('=')[1] for each in string1.split(';') if each} 
{'foo': 'bar', 'integrity': '0.95', 'ID': 'mRNA42', 'Parent': 'gene19'} 
>>> {each.split(' ')[0]:each.split(' ')[1] for each in string2.split(';') if each} 
{'': 'gene_id', 'transcript_id': '"g3.t1"'} 

,解决你所面临的问题,

def parse_single_feature_line(attributestring): 
    attributes = dict() 
    for keyvaluepair in attributestring.split(';'): 
     key,value=keyvaluepair.split('=') # you get a list when you split keyvaluepair string and not a list of list(if list of lists eg.[["this","these"],["that","those"]] then you can use - for key,value in list_of_lists:) 
     attributes[key] = value 
    return attributes 

print parse_single_feature_line(string1) 
+0

你甚至可以简单地这... dict(each.split('=')为我在string1.split(';'))更多细节检查我的答案在下面。我简化了它 –

0

他们是不同的,因此需要处理的不同。

def return_dict(string): 
    if "=" in string: 
     return dict(i.strip().split("=") for i in string.split(";")) 
    else: 
     return dict([i.strip().split(" ") for i in string.split(";") if len(i.strip().split(" ")) > 1]) 

return_dict(string1) 
return_dict(string2) 

给出:

{'ID': 'mRNA42', 'Parent': 'gene19', 'foo': 'bar', 'integrity': '0.95'} 
{'gene_id': '"g3"', 'transcript_id': '"g3.t1"'} 
+0

如果它是不同的非char?我们可以使用正则表达式.. re.split('[=]',字符串)...检查我的答案希望你会明白的 –

+0

@MohideenibnMohammed你得到的优秀版本:) –

1

您可以使用正则表达式一个全球性的解决方案:

import re 

string1 = 'ID=mRNA42;Parent=gene19;integrity=0.95;foo=bar' 
string2 = 'transcript_id "g3.t1"; gene_id "g3";' 

# Define the regular expression 
reg_exp = "([\.\-\w_]+)=([\.\-\w_]+);?|([\.\-\w_]+) \"([\.\-\w_]+)\"" 

# Get results and filter empty elements in tuples 
match = [filter(None, x) for x in re.findall(reg_exp, string1+"\n"+string2)] 

# Convert to dict 
result = {key:value for key, value in match} 

这个正则表达式中包含两大类:

A组([\.\-\w_]+)=([\.\-\w_);?和组B ([\.\-\w_]+) \"([\.\-\w_]+)\"

每个组都包含另外两组,它们将与名称和值对匹配。请注意,您可能需要调整这些组添加到您期望的名称和值,或使用(.*?)

0

解决方案一:分裂的空间,并剥去引号对结果的后半部分:

>>> key, val = 'transcript_id "g3.t1"'.split(" ", maxsplit=1) 
>>> val = val.strip('"') 
>>> key 
'transcript_id' 
>>> val 
'g3.t1' 

二解决方案(更通用):使用正则表达式来捕捉部分:

>>> import re 
>>> match = re.search(r'([a-z_]+) "(.+?)"', 'transcript_id "g3.t1"') 
>>> key, val = match.groups() 
>>> key 
'transcript_id' 
>>> val 
'g3.t1' 

如果你事先知道其中你给定的字符串或文件中有你的两种格式,你可以传递一个回调做串解析,即:

def parse_line(attributestring, itemparse): 
    attributes = dict() 
    for keyvaluepair in attributestring.split(';'): 
     if not keyvaluepair: 
      # empty string due to a trailing ";" 
      continue 
     for key, value in itemparse(keyvaluepair): 
      attributes[key] = value 
    return attributes 


def parse_eq(kvstring): 
    return kvstring.split("=") 

def parse_space(kvstring): 
    key, val = 'transcript_id "g3.t1"'.split(" ", maxsplit=1) 
    return key, val.strip('"') 

d1 = parse_line(string1, parse_eq) 
d2 = parse_line(string2, parse_space) 
0

的简化版本,您可以添加分隔符在正则表达式来拆分更多的字符串分割,

string1 = 'ID=mRNA42;Parent=gene19;integrity=0.95;foo=bar' 
string2 = 'transcript_id "g3.t1"; gene_id "g3";' 
import re 

def parse_single_feature_line(string): 
    attributes = dict(re.split('[ =]', i.strip()) for i in string.split(';') if i) 
    return attributes 

print parse_single_feature_line(string1) 
print parse_single_feature_line(string2)