Skip to main content
Hi All,

 

I look for lists comparaison. For example : i have 2 lists list1 that contains (1,2,3 values) and list2 that contains (2,3,4,5).

 

The result is 2 lists ListOut1 and ListOut2  that contain the differences :

 

ListOut1 will contains all list2 values that don't exist in list1 => ListOut1 values : 4,5

 

ListOut2 will contains all list1 values that don't exist in list2=> ListOut2 values : 1.

 

 

I dont find tranfermer that can helps me. I look for python script but i need help.

 

 

Thanks an advance.

 

FarFar 
Hi,

 

 

in Python, try something like this (nb, untested):

 

 

list1 = feature.getAttribute("list1{}.values")

 

list2 = feature.getAttribute("list2{}.values")

 

 

diff = list(set(list1) - set(list2))

 

 

for n, element in enumerate(diff):

 

    feature.setAttribute("diff{" + str(n) "}.value", element)

 

 

This assumes that each feature has at least one or more elements in "list1{}.values" and "list2{}.values". The difference will be output in "diff{}.values", which you will have to expose in the PythonCaller to make it visible in the workbench.

 

 

David
Sorry, a type in the last line. Should read:

 

 

feature.setAttribute("diff{" + str(n) + "}.value", element)

 

 

David
Sorry, was a bit quick to reply, didn't get the part about two output lists. Here's a more correct answer that also handles the case where either of the input lists are empty:

 

 

-----

 

try:     list1 = feature.getAttribute("list1{}.values") except:     list1 = i]

 

  try:     list2 = feature.getAttribute("list2{}.values") except:     list2 =  ]   diff1 = list(set(list1) - set(list2)) diff2 = list(set(list2) - set(list1))   for n, element in enumerate(diff1):     feature.setAttribute("diff1{" + str(n) + "}.value", element)   for n, element in enumerate(diff2):     feature.setAttribute("diff2{" + str(n) + "}.value", element) -----

 

 

Expose the following parameters in the PythonCaller

 

    diff1{}.values

 

    diff2{}.values

 

 

David
Hi Farfar,

 

 

I created a short test scenario. I created two lists like yours.

 

I used then the ListExploder to get all the features. In the next step I took the ChangeDetector. Here you can choose what is the original list and what should be compared. As Parameters I set Match Geometry = None. Moreover I choosed an Attribute wher my list elemets are stored (->Selected attributes).  The Added Output port gives the elements that are not in the list.

 

 

I hope that helps you,

 

best regards,

 

Stefan

 

 


Hi,

 

 

David, fmeobjects.FMEFeature.getAttribute returns "None" if specified attribute does not exist, will not throw exception. I don't think try - except clause is preferable to handle empty inputs. And, both getAttribute and setAttribute can treat a list attribute directly (except nested list). I would write this script in this case. ----- import fmeobjects def findDiff(feature):     list1 = feature.getAttribute('list1{}.values')     if list1 == None:         list1 =  ]     list2 = feature.getAttribute('list2{}.values')     if list2 == None:         list2 = ]     feature.setAttribute('diff1{}.values', list(set(list2) - set(list1)))     feature.setAttribute('diff2{}.values', list(set(list1) - set(list2))) -----   In addition, using "set" structure is efficient to find differed elements between two sets, but the order of resultant elements might change (uncontrollable). If the order of elements has to be preserved, an iterative processing will be necessary. For example: -----     feature.setAttribute('diff1{}.values', #a for a in list2 if a not in set(list1)])     feature.setAttribute('diff2{}.values', (a for a in list1 if a not in set(list2)]) -----

 

Takashi
Takashi,

 

 

thanks, you're of course right about getAttribute() returning None rather than an Exception object when the list doesn't exist.

 

 

Regarding the order, I'd say that depends on this specific case, whether it is important. Python sets have the advantage of being very fast and the resulting code is very easy to read, so I tend to prefer that solution unless order absolutely need to be preserved.

 

 

If the order is numerical, it is also easy to re-order it either using a ListSorter on the resulting list, or by using list1.sort() / list2.sort() somewhere in the Python script.

 

 

David
David, I also use "set" frequently :-)

 

Regarding the order, I agree with you. There must be cases that the ListSorter or "sort" is suitable. All depends on the requirement and actual data condition.

 


Takashi, it seems we agree 100% :-)

 

 

David
U forgot the tcl solution.

 

 

#----------------

 

 # compare list a with b

 

 #----------------

 

 proc listcompare {a b} {

 

  set diff {}

 

  foreach i $a {

 

    if { 

      lappend diff $i}

 

       }

 

    foreach i $b {

 

    if { lsearch -exact $a $i]==-1} {

 

      lappend diff  $i}

 

       }   

 

  return $diff

}

 

 

Put it in the TCL caller.

 

And in the caller tcl parameter:listcompare @Value(a) @Value(b)

 

And lists i built in a creator i.e.:

 

a=(list {1 2 3 4 5 6}]

 

b=ilist {2 4 6 8}]
..as i was at it anyway here are union and intersection.

 

 

intersection:

#----------------

 

 # compare list a with b

 

 # intersection

 

#----------------

 

 proc listcompare {a b} {

 

  set intersect {}

 

  foreach i $a {

 

    if { lsearch -exact $b $i]!=-1} {

 

      lappend intersect $i}

 

       }

 

    foreach i $b {

 

    if {Âlsearch -exact $a $i]!=-1} {

 

      lappend intersect  $i}

 

       }   

 

  set intersect  

  return $intersect

}

 

 

union:

 

#----------------

 

 # compare list a with b

 

 # union

 

#----------------

 

 proc listcompare {a b} {

 

 

 

  set union -concat $a $b]

 

  set union }lsort -unique $union]

 

      

 

  return $union

}


Reply