Question

Getting values from a list that is one element of another list

  • 21 February 2024
  • 3 replies
  • 72 views

Badge +8

Hello,

I have objects, that have a list with a number of different attributes. One of the attributes on that list is another list with a few attributes. Both lists contain 1 - n elements (if either one of the lists is empty, the object is not valid). So, a bit more visual:

 

Object1.list1[0].attrib1

Object1.list1[0].list2[0].Attr1

Object1.list1[0].list2[0].Attr2

Object1.list1[0].list2[1].Attr1

Object1.list1[0].list2[1].Attr2

Object1.list1[1].attrib1

Object1.list1[1].list2[0].Attr1

Object1.list1[1].list2[0].Attr2

Object1.list1[1].list2[1].Attr1

Object1.list1[1].list2[1].Attr2

 

And so on. What I want to do is check all list2.Attr1 for a certain value, then add list2.Attr2 as an attribute on Object1 (for easier processing and reporting). Due to a large volume of data it isn’t really feasible to use ListExploders (I’m already running into memory issues as it is), so I thought I’d try the Pythoncaller. So far this is what I’ve tried:

    def input(self, feature):
        first_list = feature.getAttribute('list1{}')
        for fl in first_list:
            second_list = fl.list2{}
            for sl in second_list:
                if sl.Attr1== "Yes":
                    feature.setAttribute('Attr2', sl.Attr2)
        self.pyoutput(feature)

But it doesn’t seem to be the right way: I keep getting an error:

Python Exception <SyntaxError>: invalid syntax (<string>, line 19)

Line 19 is:

for sl in second_list:

So it seems that second_list = fl.list2{} isn’t doing what I thought it would be doing. I’ve tried with and without {}, which does not seem to make a difference.

How can I get this working? I’ve tried searching here, and wider, but can’t find anything that deals with this kind of nested lists. It is the best way of dealing with the type of data that I’m handling though, otherwise the number of features will explode (list1 can contain 20 items, and list2 can contain upwards of 400 items in some rare occasions).

TIA,

Stefan


3 replies

Userlevel 3
Badge +26

This isn’t a full solution, but I think it might be heading in the right direction. If you produce a dictionary with Attr1 as the keys and Attr2 as the values, you might be able to able to query against the keys being “Yes”, and then set the Object1.Attr2 to the associated value.

    def input(self, feature):
        #Define dictionary
        dict = {}

        i=0
        while i<2:
            keys = feature.getAttribute('list1{}.list2{'+str(i)+'}.Attr1')
            values = feature.getAttribute('list1{}.list2{'+str(i)+'}.Attr2')
            for key, value in zip(keys, values):
                dict[key] = value
            i+=1

        #Return Attr2 value if Yes found in key
        for k,v in dict.items():
           if k == "Yes":
              feature.setAttribute('Attr2',v) 

        self.pyoutput(feature)

 

Badge +8

Hi Dustin,

 

Thanks, I’ll give that a try. I was hoping to avoid a solution like that, because it adds a lot of memory overhead (essentially duplicating the list-structure in a dictionary). 

By using a for-in over the existing structure I think I’d use less memory (and memory availability is quite a problem with the amount of data I have to process - throwing extra hardware at it would of course solve that, but that is not something which is easily or quickly done in my organization)

Badge +8

Also couldn’t get that method to work. I may need to rethink my approach, may use exploders after all, or concatenators or something...

Reply