Skip to main content
So, lists are hurting my brain again. For some reason I just can't get my head around the FME implementation despite being fine with arrays in general.

 

 

For each feature I'd like to create an empty list at the start of the workspace, with a structure like this:

 

 

_list._x

 

_list._y

 

_list._text

 

 

Then, at various points during the workspace I need to push a new element onto the end of the list (doesn't matter which end).

 

So half-way through, the list may be:

 

 

_list{0}._x = 123

 

_list{0}._y = 456

 

_list{0}._text = "text"

 

 

and at the end it may be:

 

_list{0}._x = 123

 

_list{0}._y = 456

 

_list{0}._text = "text"

 

_list{1}._x = 999

 

_list{1}._y = 666

 

_list{1}._text = "hello world"

 

_list{2}._x = 321

 

_list{2}._y = 753

 

_list{2}._text = "goodbye world"

 

 

 

At the end of the workspace I'll ListExplode it. That part I know how to do.

 

 

So two requirements:

 

a) How do I declare the empty list.

 

b) How do I populate it?

 

 

If populating the list (b) automatically instantiates it if it doesn't exist, then (a) can be skipped.

 

 

Thanks
Hi Jonathan,

 

 

Do you necessarly need to create one (empty) list to contain the elements?

 

Since eventually you are exploding the list(s), why not creating individual lists (listbuilder or listexpressionpopulator)?

 

Cheers,

 

Itay
Hi Itay,

 

  Well I guess I could create separate lists but then there'd be 7 or 8 of them and that just seems ugly.

 

As the structure of the list contents will always be the same the logical thing to do is to use the same list and stick the stuff onto the end of it.

 

Would I be right in thinking FME doesn't support that then?

 

 

Thanks,

 

Jonathan
Even worse, it looks like you can only explode one list per exploder transformer. So I'd need to create 9 different lists and then use 9 chained ListExploders!

 

 

Surely there's a better way?
Hi Jonathan,

 

You're correct, I think, that there's no standard way to add an item to the top/bottom of the list, or to pop an element off it.

 

 

After a brief think I'm wondering if you can do this by creating a separate feature for the information to be added, then merging it back on with a FeatureMerger - and in that way adding it to the list. Something like that.

 

 

You'd probably wrap it up in a custom transformer then it would be available whenever needed. I can have a try, but I'm away from the office for VAR meetings so I'm not sure I'll find time for a couple of weeks at least.

 

 

Hope this helps

 

 

Mark
If you're no stranger to Python, remember that it is possible and quite easy to manipulate list items using the PythonCaller. Examples:

 

  • a_list_of_MyListAttribute_values = feature.getAttribute("MyList{}.MyListAttribute")
  • MyListAttribute_item_no_5 = feature.getAttribute("MyList{5}.MyListAttribute")
It is also possible to explode lists using Python and fmeobjects. Example:

 

 

for this_value in a_list_of_MyListAttribute_values:

 

    my_new_feature = fmeobjects.FMEFeature()

 

    my_new_feature.setAttribute("MyAttribute", this_value)

 

    self.pyoutput(my_new_feature)

 

 

Note that you will have to use the Class implementation of the PythonCaller for this to work.

 

 

Be sure to look at the fmeojects API documentation for the details:

 

<FME>\\fmeobjects\\python\\apidoc\\index.html

 

 

Good luck!

 

 

David
I ended up just going "around" the problem.

 

I wanted the list so I could create a point at each item with an attribute - all to be done neatly at the end.

 

 

Final solution - I just created a new connection to a customTransformer which created the point and then piped it straight to the end in parrallel. Ugly as sin (crossing connectors all over), but it works.
Below is an example of creating a list with Python. The purpose of this list is to test if a roll number and civic address has already been passed by a previous feature. If not it adds the roll number and civic address to the list and outputs the feature. If not it returns and the feature is not output.

 

 

To implement this you need a Python Caller on your canvas. I have my Python script in an external file in the same folder as the FME script, named  "fme_classes.py". In the PythonCallerParameters, for Python script enter "import fme_classes" (this imports fme_classes.py). In the Class or Function to Process Features box, enter "fme_classes.ListPopulater". 

 

 

Before the PythonCaller I make an attribute called "rollNumber_civicAddress" for each feature with the roll number concatenated to the civic address.

 

 

The __init__() method is the constructor. Here you create your empty list. This method gets called only one time.

 

 

The input() method gets called each time a feature passes through the transformer. Here you test for the list value and enter it or not.

 

 

The close() method is not needed here. You could use it to collect all of the features and then output them all at once in another situation.

 

 

Hope this helps.

 

  import pyfme import __main__       #--------------------ListPopulater BEGINS--------------------------------------- ''' Creates a list, and then populates the list, testing if a given value is already in the list. Only outputs the feature if the list does not yet have the value ''' class ListPopulater():     def __init__(self):         self.aList = Â] # Empty list that gets populated during input       def input(self,feature):         rollNumber_civicAddress = feature.getAttribute("rollNumber_civicAddress")         if rollNumber_civicAddress in self.aList: # If the list already has this value...             return         self.aList.append(rollNumber_civicAddress) # Otherwise add the value and output the feature         self.pyoutput(feature)       def close(self):         pass # Not needed here   #--------------------ListPopulater ENDS-----------------------------------------

Reply