Mark
Mark

Reputation: 385

python join lines with a specific string

I have an XML string output from a code. From the output I would like to join two lines that have a 'predicted_serotype' string in them (this string is known as diff_string):

 <result type="MLST" value="96">
      <result_data type="profile" value="43,47,49,49,41,15,3"/>
      <result_data type="QC_minimum_consensus_depth" value="7"/>
      <result_data type="QC_max_percentage_non_consensus_base" value="10.0"/>
      <result_data type="QC_percentage_coverage" value="100"/>
      <result_data type="QC_minimum_consensus_depth_for_all_loci" value="7,17,27,10,25,18,22" diff:update-attr="value:7,17,27,10,24,18,22"/>
      <result_data type="QC_complete_pileup" value="TRUE"/>
      <result_data type="QC_mean_consensus_depth" value="17.67"/>
      <result_data type="QC_max_percentage_non_consensus_base_for_all_loci" value="10.0, 6.25, 3.45, 9.09, 5.88, 5.26, 5.41"/>
      <result_data type="QC_mean_consensus_depth_for_all_loci" value="17.67, 32.49, 34.09, 23.44, 35.57, 29.02, 39.08" diff:update-attr="value:17.67, 32.49, 34.09, 23.44, 34.24, 29.02, 39.08"/>
      <result_data type="QC_traffic_light" value="GREEN"/>
      <result_data diff:insert="" type="predicted_serotype" diff:add-attr="type;value" value="('Schwarzengrund (Achtman)', 168), ('Schwarzengrund (PHE)', 83), ('Blockley (Achtman)', 1), ('Uppsala (Achtman)', 1), ('Oslo (Achtman)', 1), ('Schwarzengru (Achtman)', 1), ('Iv Rough:Z4,Z32:- (Achtman)', 1)"/>
      <result_data type="predicted_serotype" value="('Schwarzengrund (PHE)', 13)" diff:delete=""/>
</result>
<gastro_prelim_st reason="not novel" success="false">
      <type st="96"/>
</gastro_prelim_st>

I have written this code but it only adds a new line rather than joining the two lines:

diff_list = diff.split("\n")
    for n,line in enumerate(diff_list):
        if "predicted_serotype" in line:
            diff_list[n] = "\n"+line.strip()
        else:
            diff_list[n]=line.rstrip()

    print("\n".join(diff_list))

What I would like is an output like this:

<result type="MLST" value="96">
          <result_data type="profile" value="43,47,49,49,41,15,3"/>
          <result_data type="QC_minimum_consensus_depth" value="7"/>
          <result_data type="QC_max_percentage_non_consensus_base" value="10.0"/>
          <result_data type="QC_percentage_coverage" value="100"/>
          <result_data type="QC_minimum_consensus_depth_for_all_loci" value="7,17,27,10,25,18,22" diff:update-attr="value:7,17,27,10,24,18,22"/>
          <result_data type="QC_complete_pileup" value="TRUE"/>
          <result_data type="QC_mean_consensus_depth" value="17.67"/>
          <result_data type="QC_max_percentage_non_consensus_base_for_all_loci" value="10.0, 6.25, 3.45, 9.09, 5.88, 5.26, 5.41"/>
          <result_data type="QC_mean_consensus_depth_for_all_loci" value="17.67, 32.49, 34.09, 23.44, 35.57, 29.02, 39.08" diff:update-attr="value:17.67, 32.49, 34.09, 23.44, 34.24, 29.02, 39.08"/>
          <result_data type="QC_traffic_light" value="GREEN"/>
          <result_data diff:insert="" type="predicted_serotype" diff:add-attr="type;value" value="('Schwarzengrund (Achtman)', 168), ('Schwarzengrund (PHE)', 83), ('Blockley (Achtman)', 1), ('Uppsala (Achtman)', 1), ('Oslo (Achtman)', 1), ('Schwarzengru (Achtman)', 1), ('Iv Rough:Z4,Z32:- (Achtman)', 1)"/><result_data type="predicted_serotype" value="('Schwarzengrund (PHE)', 13)" diff:delete=""/>
    </result>
    <gastro_prelim_st reason="not novel" success="false">
          <type st="96"/>
    </gastro_prelim_st>

Upvotes: 0

Views: 66

Answers (2)

Yoel Nisanov
Yoel Nisanov

Reputation: 1054

That's the most efficient way I found to do it.

I tried to keep the code as explainable as I could.. you could shorten it if you'd like (;

goal_str = 'predicted_serotype'
lines = text.split('\n')
line_indexes = [lines.index(elem) for elem in lines if elem.find(goal_str) > -1]
desired_text = lines[line_indexes[0]] + ''.join([lines[index].strip() for index in line_indexes[1:]])
[lines.pop(index) for index in line_indexes[1:]]
lines[line_indexes[0]] = desired_text
fixed_text = '\n'.join(lines)
print(fixed_text)

Upvotes: 0

Maxime
Maxime

Reputation: 858

This should do the trick, we look for the first occurence of a line with predicted_serotype, and then if we meet another occurence, we remove it and add it to the first occurence.

diff_list = diff.split("\n")
first_serotype_line_nbr = 0

for n,line in enumerate(diff_list):
    if "predicted_serotype" in line:
        if first_serotype_line_nbr == 0:
            first_serotype_line_nbr = n
        else:
            diff_list[first_serotype_line_nbr] += line.rstrip()
            del(diff_list[n])
    else:    
        diff_list[n]=line.rstrip()

print("\n".join(diff_list))

Upvotes: 1

Related Questions