Parse backslash-delimited hierarchy path (varying number of levels)

90 Views Asked by At

I have hierarchy paths with varying numbers of levels (up to 4):

FACILITIES \ PARK
ROADS \ GRASS/TURF BLVD MAINTENANCE
ROADS \ SIDEWALKS \ REPLACEMENT
FACILITIES \ PARKING - MAIN ST
RECREATION \ BANDSHELL \ PROPERTY \ BUILDING-GENERAL
FACILITIES \ FIREHALL \ PLUMBING
FACILITIES

I want to parse the levels at the _\_ delimiter and insert the values into Maximo database columns:

  • WOEQ1
  • WOEQ2
  • WOEQ3
  • WOEQ4

(The length of those columns is only 10 right now. I will create proper custom columns with longer lengths later.)


What I've tried:

I've figured out how to parse the levels and insert the values into columns — IF (and that's a big IF) there are always 4 levels:

#Auto-script on WORKORDER
h = mbo.getString("HIERARCHYPATH")
mbo.setValue("WOEQ1", (h.split(' \\ '))[0][:10])
mbo.setValue("WOEQ2", (h.split(' \\ '))[1][:10])
mbo.setValue("WOEQ3", (h.split(' \\ '))[2][:10])
mbo.setValue("WOEQ4", (h.split(' \\ '))[3][:10])

But of course, I won't always have 4 levels. I can have any number of levels between 1-4.


How can I parse the backslash-delimited hierarchy path (with a varying number of levels)?

2

There are 2 best solutions below

4
On BEST ANSWER

You can let "normal" splitting divide up your rows

>>> s = """\
... FACILITIES \ PARK
... ROADS \ GRASS/TURF BLVD MAINTENANCE
... ROADS \ SIDEWALKS \ REPLACEMENT
... FACILITIES \ PARKING - MAIN ST
... RECREATION \ BANDSHELL \ PROPERTY \ BUILDING-GENERAL
... FACILITIES \ FIREHALL \ PLUMBING
... FACILITIES
... """
>>> for row in s.splitlines():
...    print(row.split(" \\ "))
...
['FACILITIES', 'PARK']
['ROADS', 'GRASS/TURF BLVD MAINTENANCE']
['ROADS', 'SIDEWALKS', 'REPLACEMENT']
['FACILITIES', 'PARKING - MAIN ST']
['RECREATION', 'BANDSHELL', 'PROPERTY', 'BUILDING-GENERAL']
['FACILITIES', 'FIREHALL', 'PLUMBING']
['FACILITIES']

Then you can iterate over your returned list, setting each value

max_col_length = 10  # to be updated by author
for row in s.splitlines():
    for index, atom in enumerate(row.split(" \\ "), 1):  # count from 1
        mbo = "create a new row"  # not shown by author
        mbo.setValue("WOEQ{}".format(index), atom[:max_col_length])
    "INSERT row if processing rows individually"
"INSERT all rows if able to upload them all at the same time"

If you need to always provide at least 4 (or N) members in your list, you could use itertools.repeat to fill in the remaining values

>>> import itertools
>>> mylist = ['RECREATION', 'BANDSHELL', 'PROPERTY']
>>> mylist.extend(list(itertools.repeat(None, 4 - len(mylist))))
>>> print(mylist)
['RECREATION', 'BANDSHELL', 'PROPERTY', None]
0
On

This is the script I ended up going with (it's a variation of @ti7's answer).

The script nulls-out existing values in scenarios where the new hierarchypath has less than four levels.

parts = s.split(r' \ ')
for i, part in enumerate(parts, 1):
    mbo.setValue(col_prefix + str(i), part)
for i in range(len(parts)+1, 5):
    mbo.setValueNull(col_prefix + str(i))