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"?

  • July 19, 2018
  • 8 replies
  • 110 views

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".

This post is closed to further activity.
It may be an old question, an answered question, an implemented idea, or a notification-only post.
Please check post dates before relying on any information in a question or answer.
For follow-up or related questions, please post a new question or idea.
If there is a genuine update to be made, please contact us and request that the post is reopened.

8 replies

bruceharold
Supporter
Forum|alt.badge.img+19
  • Supporter
  • 344 replies
  • 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
  • 12 replies
  • 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
Celebrity
  • 7842 replies
  • July 20, 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
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
  • 12 replies
  • July 20, 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
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
Supporter
Forum|alt.badge.img+19
  • Supporter
  • 344 replies
  • July 20, 2018
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+20
  • Safer
  • 3719 replies
  • 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+20
  • Safer
  • 3719 replies
  • July 21, 2018
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
Celebrity
  • 7842 replies
  • 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.