CEamonn
CEamonn

Reputation: 925

Split file into dictionary in one statement

I have a file that looks like

device1.dev:manf:up
device2.dev:manf:up
device3.dev:manf:up
device4.dev:manf:up
device5.dev:manf:down

I'm trying to create a dictionary holding the device name and status. At the minute my code looks like

        with open(r_file) as f:
            devices = (i.split(":")[0].split(".")[0] for i in f)

This gets me all the devices. I can also easily do

with open(r_file) as f:
            devices = (i.split(":")[2] for i in f)

to get the status, but

devices = {i.split(":")[0].split(".")[0] for i in f:i.split(":")[2] for i in f}

returns invalid syntax.

Is there a good way to do achieve a dictionary of

{device1:up, device2:up, device3:up, device4:up, device5:down}

that I'm missing?

Upvotes: 1

Views: 79

Answers (5)

Ajax1234
Ajax1234

Reputation: 71471

You can use re:

import re
final_data = dict([re.sub('\.[a-zA-Z:]+:', ' ', i).split() for i in open('filename.txt')])

Output:

{'device5': 'down', 'device4': 'up', 'device1': 'up', 'device3': 'up', 'device2': 'up'}

Upvotes: 0

Tony Tuttle
Tony Tuttle

Reputation: 632

This worked for me given your example data and desired results.

with open(r_file, 'r') as f:
    devices = {i.split('.', 1)[0]: i.rsplit(':', 1)[-1].strip() for i in f.readlines()}

Note that using rsplit() to get the status allows you to grab just the stuff you want from the right end of the string. Also, I used strip() to remove the newlines.

Upvotes: 2

cdlane
cdlane

Reputation: 41905

I'd say to use re.split() but keep it simple:

import re

with open(r_file) as source:
    devices = dict(re.split(r"\..*:", line.rstrip()) for line in source)

print(devices)

OUTPUT

% python3 test.py
{'device1': 'up', 'device2': 'up', 'device3': 'up', 'device4': 'up', 'device5': 'down'}
%

Upvotes: 2

Alex
Alex

Reputation: 19124

You can split on multiple delimiters by replacing one delimiter with another before using Python's str.split:

with open(r_file) as f:
    devices = dict(i.rstrip().replace('.', ':').split(':')[::3] for i in f)

or you can use a regular expression (the re module):

with open(r_file) as f:
    devices = dict(re.match('(.*)\..*:(.*)', i).groups() for i in f)

Both return:

{'device1': 'up',
 'device2': 'up',
 'device3': 'up',
 'device4': 'up',
 'device5': 'down'}

Upvotes: 0

RomanPerekhrest
RomanPerekhrest

Reputation: 92894

Alternative solution with re.search() function:

import re

with open(r_file) as f:
    pat = re.compile(r'^([^.]+).+?([^:]+)$')
    devices = dict(pat.search(r).groups() for r in f.read().splitlines())

print(devices)

The output:

{'device1': 'up', 'device2': 'up', 'device3': 'up', 'device4': 'up', 'device5': 'down'}

Upvotes: 0

Related Questions