Nicholas I
Nicholas I

Reputation: 39

grouping elements in the list based in sequential order

I am new to python. Got a complex task to work on.

I have a text file containing a sections separated by comments and commands are in between them. There are multiple sections in the files. I want to extract the commands related it's own section and create a list out of it.

Eample:

test.txt

#section 1
ls -1
sudo apt-get install vim

#section 2
sudo apt-get install ruby

output:

list1 = ['ls -1','sudo apt-get install vim']
list2 = ['sudo apt-get install ruby']

Upvotes: 2

Views: 94

Answers (3)

Padraic Cunningham
Padraic Cunningham

Reputation: 180522

Use groupby:

from itertools import groupby

with open("test.txt") as f:
    for k, v in groupby(map(str.strip, f), lambda x: not x.startswith("#")):
        if k:
            print(list(filter(None, v)))
['ls -1', 'sudo apt-get install vim']
['sudo apt-get install ruby']

For python2 use itertools.imap and itertools.ifilter

You can create a list of lists with a list comprehension:

from itertools import groupby
with open("test.txt") as f:
    out = [list(filter(None, v)) for k, v in groupby(map(str.strip, f), lambda x: not x.startswith("#")) if k]
print(out)
['ls -1', 'sudo apt-get install vim'], ['sudo apt-get install ruby']]

If you want then stored so you can access by name use a dict:

from itertools import groupby
from itertools import count
with open("test.txt") as f:
    d = {}
    cn = count(1)
    for k, v in groupby(map(str.strip, f), lambda x: not x.startswith("#")):
        if k:
            d["list_{}".format(next(cn))] = list(filter(None, v))

print(d)
{'list_2': ['sudo apt-get install ruby'], 'list_1': ['ls -1', 'sudo apt-get install vim']}

Upvotes: 1

JuniorCompressor
JuniorCompressor

Reputation: 20025

You can create an initially empty list of sections. Every time you find a line that starts with # you append a sublist. Otherwise, if we encountered a section so far and the line is not empty, we add the line to the last inserted sublist of sections.

sections = []
with open("test.txt", "r") as f:
    for line in map(str.strip, f):
        if line.startswith('#'):
            sections.append([])
        elif sections and line:
            sections[-1].append(line)

Result:

[['ls -1', 'sudo apt-get install vim'], ['sudo apt-get install ruby']]

Upvotes: 2

Abhijit
Abhijit

Reputation: 63777

Your problem is a simple grouping exercise, which can simply be achieved by keeping track of a section start for indicating that the subsequent lines should be appended to a new list

Implementation

output = [[]]
with open("test.txt") as fin:
    #from itertools import imap
    for line in map(str.strip, fin):
    #for line in imap(str.strip, fin):
        if line:
            if line.startswith('#'):
                output.append([])
                continue
            output[-1].append(line)
    output = output[1:]

Assuming your file contains

test.txt

#section 1
ls -1
sudo apt-get install vim

#section 2
ls -lrt
sudo apt-get install ruby

output

[['ls -1', 'sudo apt-get install vim'], ['ls -lrt', 'sudo apt-get install ruby']]

Upvotes: 2

Related Questions