Skip to main content
Solved

duplicate attributes on value-ranges


loldedub
Contributor
Forum|alt.badge.img+2

I have a dataset with attributes where in two columns the start and end of a range (postalcode)

is it possible to duplicate the attributes with the missing postalcodes?

example:

range tels me: 

from 7595AM  to 7595AP

there are 2 postalcodes missing. 7595AN and 7595AO.

from this attribute i would like to duplicate it to 4 attributes for each of the seperate postalcodes.

 

thanx in advance.

 

i am using FME Form 2024.1

Best answer by hkingsbury

Firstly, thanks to ChatGPT for helping with this - credit where credit is due!

The below python code will return a feature with an attribute new_code containing each of the missing codes between the specified start and end ones. In you python caller, make sure you expose new_code

import fme
import fmeobjects


class FeatureProcessor(object):

    def __init__(self):
        pass

    def has_support_for(self, support_type: int):
        return support_type == fmeobjects.FME_SUPPORT_FEATURE_TABLE_SHIM

    def increment_code(self, code):
        # Split the code into numeric and alphabetic parts
        numeric_part = int(code[:4])
        alpha_part = code[4:]

        # Convert alpha part to number
        alpha_number = (ord(alpha_part[0]) - ord('A')) * 26 + (ord(alpha_part[1]) - ord('A'))

        # Increment alpha number
        alpha_number += 1

        # If alpha number exceeds the range, reset and increment numeric part
        if alpha_number >= 26 * 26:
            alpha_number = 0
            numeric_part += 1

        # Convert back to code
        new_alpha_part = chr(alpha_number // 26 + ord('A')) + chr(alpha_number % 26 + ord('A'))
        return f"{numeric_part:04d}{new_alpha_part}"


    def input(self, feature: fmeobjects.FMEFeature):
        start = feature.getAttribute('postcode_van')
        end = feature.getAttribute('postcode_tot')

        curr = self.increment_code(start)

        while curr != end:
            feature.setAttribute('new_code', curr)
            self.pyoutput(feature)
            curr = self.increment_code(curr)

    def close(self):
        pass

    def process_group(self):
        pass

 

View original
Did this help you find an answer to your question?

3 replies

hkingsbury
Celebrity
Forum|alt.badge.img+53
  • Celebrity
  • Best Answer
  • August 14, 2024

Firstly, thanks to ChatGPT for helping with this - credit where credit is due!

The below python code will return a feature with an attribute new_code containing each of the missing codes between the specified start and end ones. In you python caller, make sure you expose new_code

import fme
import fmeobjects


class FeatureProcessor(object):

    def __init__(self):
        pass

    def has_support_for(self, support_type: int):
        return support_type == fmeobjects.FME_SUPPORT_FEATURE_TABLE_SHIM

    def increment_code(self, code):
        # Split the code into numeric and alphabetic parts
        numeric_part = int(code[:4])
        alpha_part = code[4:]

        # Convert alpha part to number
        alpha_number = (ord(alpha_part[0]) - ord('A')) * 26 + (ord(alpha_part[1]) - ord('A'))

        # Increment alpha number
        alpha_number += 1

        # If alpha number exceeds the range, reset and increment numeric part
        if alpha_number >= 26 * 26:
            alpha_number = 0
            numeric_part += 1

        # Convert back to code
        new_alpha_part = chr(alpha_number // 26 + ord('A')) + chr(alpha_number % 26 + ord('A'))
        return f"{numeric_part:04d}{new_alpha_part}"


    def input(self, feature: fmeobjects.FMEFeature):
        start = feature.getAttribute('postcode_van')
        end = feature.getAttribute('postcode_tot')

        curr = self.increment_code(start)

        while curr != end:
            feature.setAttribute('new_code', curr)
            self.pyoutput(feature)
            curr = self.increment_code(curr)

    def close(self):
        pass

    def process_group(self):
        pass

 


bwn
Evangelist
Forum|alt.badge.img+26
  • Evangelist
  • August 15, 2024

Having done similar in FME, then I’ve used Cloner for this.

 

Steps would be:

  1. Convert the Postcode AlphaNumerics into Pure Numbers.   Effectively the form you have is that each “Number” is a Decimal Number 0-9 , or a Letter Number A-Z (26 Letter Numbers).   This 10+26 = A Base36 Number
  2. Convert the PostCode Base36 “Numbers” into Decimal Numbers (Base10) using BaseConvertor
  3. Use Cloner to create the extra intermediate features/rows based on the Difference between the Base10 postcode_tot_decimal number and the Base 10 postcode_vav_decimal number
  4. Use AttributeCreator to set each new Feature/Row to a “postcode_sequence” number being postcode_van_decimal + the Cloner Sequence Number
  5. Back convert the postcode_sequence Decimal Numbers (Base10) back to Base36 to get them back into Postcode Alphanumeric Format.
  6. ListBuilder to wrap it into a List (Grouping into Lists effectively dissolves the Features into special List Attributes horizontally on the Feature)
  7. Join the calculated Lists back into the Source Features with FeatureJoiner

 

 


*Edit*

Extra little Tester step to handle when an “Intermediate” Postcode has a 0-9 Number in either the 5th character or the 6th character, which is invalid.

 

 


loldedub
Contributor
Forum|alt.badge.img+2
  • Author
  • Contributor
  • August 20, 2024

Thanks for the options.

I tried both of them.

in my proces within FME option 1 worked well.

i just had to implement de postcode_van en postcode_tot.

The second one keeps running and gave me an out of memory.

 

thanks again.

kind regards

Laurens

 


Reply


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