Solved

How do I obtain list index information using PythonCaller?

  • 3 August 2021
  • 7 replies
  • 2 views

The problem:

I have two lists which are related to each other by way of index so lets say we have the following format -

 

List 1 (contains 4 Elements)

List 2 (contains 4 Elements)

 

The Elements in each list relate to one another so Element 0 in List 1 is directly relatable to Element 0 in List 2. Element 1 in List 1 is directly relatable to Element 1 in List 2 and so on and so forth for the rest of the Elements.

 

What I'd like to Achieve:

If any Element stored in List 1 = "foo" -- I would like to remove it as well as the related Element in List 2. I think this is easily achieved if it is possible to extract not just the attribute of the Element in the lists, but the Element Index as well. How do I do this?

 

I am able to extract the attribute name of each Element easily by using:

my_list = feature.getAttribute('my_list{})

 

Thanks in Advance.

 

icon

Best answer by warrendev 4 August 2021, 01:35

View original

7 replies

Badge

Hey @mrajmoss​ would you be able to share an example workspace?

Badge +16

Try this. Not sure if this is what you are looking for, but maybe this will help. 

 

Let's say I have 2 lists called list1 and list2.

list1 = ['foo', 'value2', 'value3']
list2 = ['value1', 'value2', 'value3']

I want to iterate through the list and when I find a value in list1 that matches 'foo', I will remove that from list1 as well as the item at that specific index in list2.

my_list1 = feature.getAttribute('list1{}')
my_list2 = feature.getAttribute('list2{}')
        
for index, list1_value in enumerate(my_list1):
        if list1_value == 'foo':
                del my_list1[index]
                del my_list2[index]
feature.setAttribute('my_list1{}', my_list1)
feature.setAttribute('my_list2{}', my_list2)

 

Now 'foo' is removed from my_list1{} and the value is removed from my_list2{} at the same index.

new_list 

Try this. Not sure if this is what you are looking for, but maybe this will help. 

 

Let's say I have 2 lists called list1 and list2.

list1 = ['foo', 'value2', 'value3']
list2 = ['value1', 'value2', 'value3']

I want to iterate through the list and when I find a value in list1 that matches 'foo', I will remove that from list1 as well as the item at that specific index in list2.

my_list1 = feature.getAttribute('list1{}')
my_list2 = feature.getAttribute('list2{}')
        
for index, list1_value in enumerate(my_list1):
        if list1_value == 'foo':
                del my_list1[index]
                del my_list2[index]
feature.setAttribute('my_list1{}', my_list1)
feature.setAttribute('my_list2{}', my_list2)

 

Now 'foo' is removed from my_list1{} and the value is removed from my_list2{} at the same index.

new_list 

This is exactly what I'm looking for, however using it does not give the same results that you seem to get.

 

For me this method produces the following results:

list1 = ['value2', 'value2', 'value3']
list2 = ['value1', 'value2', 'value3']

Whereby anytime the value 'foo' is encountered it is replaced by the value it encounters next within the list. The list size is not reduced, but the values are changed.

 

Here is another example for clarification:

 

Starting data:

list1 = ['foo', 'value2', 'foo', 'value4']
list2 = ['value1', 'value2', 'value3', 'value4']

Output using your method above:

list1 = ['value2', 'value2', 'value4', 'value4']
list2 = ['value2', 'value2', 'value4', 'value4']

 

Badge +10

To replace the value with the next in the list you can do something like this

def processFeature(feature):
    my_list1 = feature.getAttribute('list1{}')
    my_list2 = feature.getAttribute('list2{}')
        
    for index, list1_value in enumerate(my_list1):
        if list1_value == 'foo':
            feature.setAttribute('list1{'+str(index)+'}',my_list1[index+1])
            feature.setAttribute('list2{'+str(index)+'}',my_list1[index+1])

It's not clear from your example whether you want the list item in list 2 to be replaced with the list item from list 1 or the next list item in list 2 when foo is encountered. You would have to handle the exception if foo was ever encountered as the last item in the list

 

To replace the value with the next in the list you can do something like this

def processFeature(feature):
    my_list1 = feature.getAttribute('list1{}')
    my_list2 = feature.getAttribute('list2{}')
        
    for index, list1_value in enumerate(my_list1):
        if list1_value == 'foo':
            feature.setAttribute('list1{'+str(index)+'}',my_list1[index+1])
            feature.setAttribute('list2{'+str(index)+'}',my_list1[index+1])

It's not clear from your example whether you want the list item in list 2 to be replaced with the list item from list 1 or the next list item in list 2 when foo is encountered. You would have to handle the exception if foo was ever encountered as the last item in the list

 

Hi thanks for commenting, I do not wish to replace anything in either list, I wish to remove any cases of "foo" that I find in List 1, then I wish to remove the index in List 2 that matches where "foo" was in List 1.

 

So if "foo" was found at index 3 in List 1, I would remove it and then also find index 3 in list 2 and remove that as well (As list 2 is related to list 1 via the indexes).

Does this help explain it better?

Badge +16

This is exactly what I'm looking for, however using it does not give the same results that you seem to get.

 

For me this method produces the following results:

list1 = ['value2', 'value2', 'value3']
list2 = ['value1', 'value2', 'value3']

Whereby anytime the value 'foo' is encountered it is replaced by the value it encounters next within the list. The list size is not reduced, but the values are changed.

 

Here is another example for clarification:

 

Starting data:

list1 = ['foo', 'value2', 'foo', 'value4']
list2 = ['value1', 'value2', 'value3', 'value4']

Output using your method above:

list1 = ['value2', 'value2', 'value4', 'value4']
list2 = ['value2', 'value2', 'value4', 'value4']

 

@mrajmoss​ I've attached an example workspace that hopefully will help.

example 

This is exactly what I'm looking for, however using it does not give the same results that you seem to get.

 

For me this method produces the following results:

list1 = ['value2', 'value2', 'value3']
list2 = ['value1', 'value2', 'value3']

Whereby anytime the value 'foo' is encountered it is replaced by the value it encounters next within the list. The list size is not reduced, but the values are changed.

 

Here is another example for clarification:

 

Starting data:

list1 = ['foo', 'value2', 'foo', 'value4']
list2 = ['value1', 'value2', 'value3', 'value4']

Output using your method above:

list1 = ['value2', 'value2', 'value4', 'value4']
list2 = ['value2', 'value2', 'value4', 'value4']

 

Thanks a lot, this completely solved it for me. The part of the code I was missing was:

 

        # Remove the existing list attributes from the feature so we can reset them
        feature.removeAttribute('mylist1{}')
        feature.removeAttribute('mylist2{}')

So I wasn't clearing the values in FME before setting them again. Great work!

Reply