Skip to main content
Question

How to replace consecutive numbers in an attribute list from "1,2,3,4,7,10,13,14,15,16" to "1-4,7,10,13,14-16"?


Forum|alt.badge.img

I have an attribute with a value of a list of numbers separated by commas. I would like for all the consecutive numbers in the list to get replaced by one dash in between the first and last consecutive number instead of having each number represented. Basically I would like this "1,2,3,4,5,7,9,14,15" to become this "1-5,7,9,14-15".

8 replies

bruceharold
Contributor
Forum|alt.badge.img+17
  • Contributor
  • July 19, 2018

Hi

You can modify this Python function, as-is it returns a list of lists.

>>> runs([1,2,3,4,7,10,13,14,15,16])

 

[[1, 2, 3, 4], [7], [10], [13, 14, 15, 16]]
  # Function to build runs of OID values
def runs(oidList): 
    runs = []
    for oid in oidList:
        if not runs:
            runs.append([oid])
            continue
        if runs[-1][-1] == oid - 1:
                runs[-1].append(oid)
        else:
            runs.append([oid])
    return runs

Forum|alt.badge.img
  • Author
  • July 19, 2018
I have attached a sample of the data to work with. The attribute values I would like to modify are the Legal_Sub values. data.zip

 

 


takashi
Influencer
  • July 20, 2018
bruceharold wrote:

Hi

You can modify this Python function, as-is it returns a list of lists.

>>> runs([1,2,3,4,7,10,13,14,15,16])

 

[[1, 2, 3, 4], [7], [10], [13, 14, 15, 16]]
  # Function to build runs of OID values
def runs(oidList): 
    runs = []
    for oid in oidList:
        if not runs:
            runs.append([oid])
            continue
        if runs[-1][-1] == oid - 1:
                runs[-1].append(oid)
        else:
            runs.append([oid])
    return runs
This is a PythonCaller script example using the "runs" function provided by @bruceharold.

 

def processFeature(feature):
    sub = feature.getAttribute('Legal_Sub')
    if sub:
        s = []
        for nums in runs(sorted([int(c) for c in sub.split(',')])):
            if 2 < len(nums):
                s.append('%s-%s' % (nums[0], nums[-1]))
            else:
                s += [str(n) for n in nums]
        feature.setAttribute('Legal_Sub'','.join(s))
        
def runs(oidList):
    <omitted below>

Forum|alt.badge.img
  • Author
  • July 20, 2018
bruceharold wrote:

Hi

You can modify this Python function, as-is it returns a list of lists.

>>> runs([1,2,3,4,7,10,13,14,15,16])

 

[[1, 2, 3, 4], [7], [10], [13, 14, 15, 16]]
  # Function to build runs of OID values
def runs(oidList): 
    runs = []
    for oid in oidList:
        if not runs:
            runs.append([oid])
            continue
        if runs[-1][-1] == oid - 1:
                runs[-1].append(oid)
        else:
            runs.append([oid])
    return runs
Do I need to have the "sorted" in there? The list is already sorted through a ListSort transformer. I'm having difficulty incorporating the Python in FME also, do I use Python Caller twice? One for each function?  Apologies, am new to working with Python inside FME.

 

 


bruceharold
Contributor
Forum|alt.badge.img+17
  • Contributor
  • July 20, 2018
krenty wrote:
Do I need to have the "sorted" in there? The list is already sorted through a ListSort transformer. I'm having difficulty incorporating the Python in FME also, do I use Python Caller twice? One for each function? Apologies, am new to working with Python inside FME.

 

 

Thanks Takashi, I was a bit lazy. @krenty

 

having 'sorted' in there is just good practice in case the code is used with an unsorted list.

 


fmelizard
Safer
Forum|alt.badge.img+18
  • Safer
  • July 21, 2018
RE: PythonCaller -- @krenty -- just put down a single PythonCaller in your flow and then paste in all the code of Takashi's as the script (and of course also including the "runs" function of Bruce's.

 

 

Cool result. Wanted to check it out so I build a sample workspace. The main trick is to tell the PythonCaller the name of the function you want it to use (in this case, processFeature). See attached: itemstoranges.fmw

 


fmelizard
Safer
Forum|alt.badge.img+18
  • Safer
  • July 21, 2018
krenty wrote:
Do I need to have the "sorted" in there? The list is already sorted through a ListSort transformer. I'm having difficulty incorporating the Python in FME also, do I use Python Caller twice? One for each function? Apologies, am new to working with Python inside FME.

 

 

RE: PythonCaller -- @krenty -- just put down a single PythonCaller in your flow and then paste in all the code of Takashi's as the script (and of course also including the "runs" function of Bruce's.

 

 

Cool result. Wanted to check it out so I build a sample workspace. The main trick is to tell the PythonCaller the name of the function you want it to use (in this case, processFeature). See attached: itemstoranges.fmw

 


takashi
Influencer
  • July 21, 2018

I would adopt the Python scripting approach as a practical solution, but this may also be an interesting exercise using geometric operations. e.g.


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings