-2

I have string like below mentioned and contain n number of lines per group and I would like to arrange the string as mentioned below ..

real   51.85ms
sys    22.41ms
usr    29.70ms
[www.ms786.com] 2345 sunset follow
Multidd    567890KB

real   61.85ms
sys    32.41ms
usr    27.70ms
[www.ms586.com] 4345 sunset follow
Multidd    4567890KB

real   51.85ms
sys    12.41ms
usr    41.70ms
[www.ms186.com] 7345 sunset follow
Multidd    8967890KB

TO

[www.ms786.com] 2345 sunset follow
Multidd    567890KB
real   51.85ms
sys    22.41ms
usr    29.70ms
Multidd    567890KB

[www.ms586.com] 4345 sunset follow
Multidd    4567890KB
real   61.85ms
sys    32.41ms
usr    27.70ms

[www.ms186.com] 7345 sunset follow
Multidd    8967890KB
real   51.85ms
sys    12.41ms
usr    41.70ms`

Could you help how it can be reshuffled in the string itself. Will really appreciate your help

Koushur
  • 167
  • 1
  • 9

2 Answers2

0

This solution does this efficiently, by locating group headers and shifting them back to their right positions:

s = """real   51.85ms
sys    22.41ms
usr    29.70ms
[www.ms786.com] 2345 sunset follow
Multidd    567890KB

real   61.85ms
sys    32.41ms
usr    27.70ms
[www.ms586.com] 4345 sunset follow
Multidd    4567890KB

real   51.85ms
sys    12.41ms
usr    41.70ms
[www.ms186.com] 7345 sunset follow
Multidd    8967890KB"""

def move_header_back(lines, header_prefix, base_index = 0):
    # Find group header positions
    group_header_positions = [base_index - 1] + [i + 1 for i in range(len(lines)) if lines[i].startswith(header_prefix)]
    # If no group positions found (there is one as we inserted `0` regardless)
    if 1 == len(group_header_positions):
        return lines
    # Shift back groups headers
    for i in range(1, len(group_header_positions)):
        group_header = lines.pop(group_header_positions[i] - 1)
        lines.insert(group_header_positions[i - 1] + 1, group_header)
    return lines

def fix_group_positions(lines):
    move_header_back(lines, header_prefix = '[',        base_index=0)
    move_header_back(lines, header_prefix = 'Multidd',  base_index=1)
    # Join back lines
    return '\n'.join(lines)

lines = [l for l in s.split('\n') if l]
print(fix_group_positions(lines))

Output:

[www.ms786.com] 2345 sunset follow
Multidd    567890KB
real   51.85ms
sys    22.41ms
usr    29.70ms
[www.ms586.com] 4345 sunset follow
Multidd    4567890KB
real   61.85ms
sys    32.41ms
usr    27.70ms
[www.ms186.com] 7345 sunset follow
Multidd    8967890KB
real   51.85ms
sys    12.41ms
usr    41.70ms
Aviv Yaniv
  • 6,188
  • 3
  • 7
  • 22
  • Thank you so much this is really amazing!. I just have one modification ..there is extra line added after the line containing sunset follow for the group. Eg real 51.85ms sys 22.41ms usr 29.70ms [www.ms786.com] 2345 sunset follow Multidd 56789 real 51.85ms sys 22.41ms usr 29.70ms [www.ms586.com] 2345 sunset follow Multidd 798798798 – Koushur Sep 09 '20 at 19:03
  • Which modification? @Asrar – Aviv Yaniv Sep 09 '20 at 19:05
  • @Yaniv I have modified my example with exact pattern – Koushur Sep 09 '20 at 19:20
  • @Asrar Updated :) – Aviv Yaniv Sep 09 '20 at 19:28
  • @Yaniv, Much appreciated. I will be embedding same thing in my code which runs for thousands of servers. Will let you know how it goes. – Koushur Sep 09 '20 at 20:01
  • @yaniv HI Yaniv , I required further improvement on this that the line starting with multidd should be always 2nd line of the string. – Koushur Sep 10 '20 at 19:29
  • @Asrar please don't change the requirements periodically. Updated. – Aviv Yaniv Sep 10 '20 at 19:45
  • Thank you so much Yaniv for your helps.. Actually data kept changing I am totally new vibe in Python. I really appreciate your help ! – Koushur Sep 10 '20 at 21:32
0

This code works by defining how lines for each block should be arranged. For example with "340125" old line 3 will become new line 0, old line 4 -> new line 1, and so on.
It will work with all block structures up to 10 lines per block, as long as the structure stays the same for all blocks.

class BlockRearrange:
    def __init__(self, order):
        self.order = list(map(int, order))
        self.blocksize = len(self.order)
    
    def reorder(self, s):
        result = ""
        lines = s.splitlines()

        for block_pos in range(0, len(lines), self.blocksize):
            part = lines[block_pos:block_pos+self.blocksize]
            part_length = len(part)

            for n in self.order:
                if n < part_length:
                    result += part[n] + "\n"
        
            if part_length < self.blocksize:
                break

        return result

# Create instance with formula for how to rearrange the blocks.
# The order-string needs to contain every line of the block,
# even those not changing positions.
br = BlockRearrange("340125")

print(br.reorder(s))
Wups
  • 2,489
  • 1
  • 6
  • 17