Skip to main content
Suppose I have some census data concerning primary language spoken at home. There would be many fields here but for the sake of simplicity, let's suppose there are only five: Cantonese, Chinese, Mandarin, Tagalog, and Tamil. Each would contain the number of households within a census unit where each language is spoken e.g. 30 for Cantonese, 150 for Chinese, 70 for Mandarin, 85 for Tagalog, and 2 for Tamil i.e. Chinese is the most common language spoken at home within this unit followed by Tagalog, Mandarin, Cantonese, and finally Tamil.

 

 

Now suppose I want to create three new fields which indicate the first, second, and third most common language spoken at home. Let's call these fields Top1, Top2, and Top3. In the example above the Top1 field value would be set to "Chinese", the Top2 field value would be set to "Tagalog", and the Top3 field value would be set to "Mandarin". In other words, I want to populate the Top1, Top2, and Top3 fields with the name of the language field based upon its value relative to the others.

 

 

I've tried playing with expressions but these would get rather large and complex given there are close to 100 language fields.

 

 

I've also tried playing with lists. This would be a great approach if I could create a list based on field name/value pairs. I could then sort (descending) by the value and extract the name e.g. language{0}.name for TOP1, language{1}.name for TOP2, and language{2}.name for TOP3.

 

 

Any direction, hints, or related thoughts are welcome as I’m stumped.

 

 

- Brooks
Hi,

 

 

I agree that creating a structured list would be a good approach.

 

 

My first inspiration was the AttributeExploder (Exploding Type: List). However, the transformer saves every attribute including hidden ones (e.g. "fme_feature_type") into the resulting list, so it would be troublesome to remove unnecessary elements before sorting.

 

 

Instead, you can create the required list directly with the AttributeCreator. Use the Text Editor to enter the attribute names as constant string values (k *****).

 

 

 

Alternatively, a TclCaller with this script can also be used to create the list. Expose the list name ( "language{}.name", "language{}.value") through the "Attributes to Expose" parameter. The script would be convenient if there were many attributes to be saved into a structured list.

 

-----

 

proc createList {} {

 

    set attributes slist "Cantonese" "Chinese" "Mandarin" "Tagalog" "Tamil"]

 

    set i 0

 

    foreach name $attributes {

 

        FME_SetAttribute "language{$i}.name" $name

 

        FME_SetAttribute "language{$i}.value" &FME_GetAttribute $name]

 

        incr i

 

    }

 

}

 

-----

 

 

After creating the list, you can use the ListSorter to sort the list elements on "language{}.value".

 

 

Takashi
P.S. It might be useful in many scenarios to create a list containing name and value pairs of selected attributes, so I published a custom transformer named "AttributeListExploder" into the FME Store.

 

Find it in your Transformer Gallery (Refresh the Gallery if it doesn't appear).
Perfect! Thank you!
What if I wanted to sort by value (descending) and name (ascending)? Any ideas?
Try using two ListSorters.

 

First, sort the list by name ascending; second, by value descending.
Nope. I want to wort by both value (descending) and name (ascending) at the same time so if theres an tie with the values, the results will be ordered by name.
The sorting method of the ListSorter seems to be stable (i.e. the relative order of the same values will not be changed), so I think that the order of the names for the same values will be preserved after sorting by values. It's similar to the operation to sort rows of the Table View of the Data Inspector by clicking two column headers one by one.
Hmm. Any other ideas? I need something like the following SQL-ish query:

 

 

SELECT * FROM LIST ORDER BY VALUE DESC, NAME;

Reply