Intersecting Lists Problem

605
14
Jump to solution
03-19-2019 03:08 PM
AlanDodson
New Contributor III

First post here, please be gentle...

I use ArcMap 10.3.1 and I'm having trouble with part of a Python script which will always be run from the Current mxd and active data frame.

I have to pass a list of layers to a function. I have given the script a list of all potential layers for this function (List 1).  Some of those potential layers will actually be in my active data frame (always at least 1), along with other layers that are not compatible with the next function (List2).  I want to only work with the potential layers that are actually present in my active data frame (List3)

I've tried the following:

import arcpy

mxd = arcpy.mapping.MapDocument("CURRENT")

df = mxd.ActiveDataFrame

List 1 = ["September", "October", "November", "December"]

List 2 = arcpy.mapping.ListLayers(df)  # layers are named September and December

List 3 = list(set.(List1).intersection(List2))

The result is an empty list when it should be September, December.

I think the syntax roughly works, but the problem is that List2 returns something similar to <layer u'September'> so the two layers with identical names are not recognized as such.  

(For context, I'll then be using List3 to print unique messages depending on the layer name returned... In case this helps)

Can anyone help me out? 

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JoshuaBixby
MVP Esteemed Contributor

This works for me:

>>> mxd = arcpy.mapping.MapDocument("CURRENT")
>>> df = mxd.activeDataFrame
>>> 
>>> List1 = ["September", "October", "November", "December"]
>>> List2 = [lyr.name for lyr in arcpy.mapping.ListLayers(mxd, data_frame=df)]
>>> List3 = list(set(List1).intersection(List2))
>>> List3
[u'September', u'December']
>>> 

View solution in original post

14 Replies
PavanYadav
Occasional Contributor II
arcpy.mapping.ListLayers(df) 

is returning a list of Layer objects. Something like this:

[<map layer u'September '>, <map layer u'December'>]

How about the following:

List2a = []
for l in List2:
    List2a.append(str(l.name))
0 Kudos
JoeBorgione
MVP Esteemed Contributor

I found this with a google search:  Python | Intersection of two lists - GeeksforGeeks 

and it suggests in method 2 something close to what you are trying:

def intersection(lst1, lst2): 
    return list(set(lst1) & set(lst2)) 
  

lst1 = [15, 9, 10, 56, 23, 78, 5, 4, 9] 
lst2 = [9, 4, 5, 36, 47, 26, 10, 45, 87] 
print(intersection(lst1, lst2)) 
That should just about do it....
0 Kudos
RandyBurton
MVP Regular Contributor

As Pavan suggests, you need to use the layer's name property in your comparison.  Try:

import arcpy 
mxd = arcpy.mapping.MapDocument("CURRENT")
df = mxd.ActiveDataFrame

List1 = ["September", "October", "November", "December"]
List2 = arcpy.mapping.ListLayers(df)  # layers are named September and December
List3 = []

for lyr in List2:
    if lyr.name in List1:
        List3.append(lyr.name)

EDIT:  As Joshua Bixby‌ shows in his code example,  line 6 in my code should read as below. See: ListLayers.

# ListLayers (map_document_or_layer, {wildcard}, {data_frame})

List2 = arcpy.mapping.ListLayers(mxd, data_frame=df)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
AlanDodson
New Contributor III

Ah, this looks promising. I didn't get to the layer name before but this looks like it could solve that. I will try it out first thing in the morning and report back.

Do you know if this method preserves the list order?

0 Kudos
RandyBurton
MVP Regular Contributor

List3 should be in the List2 (or ListLayers) order.  It is likely that it would match the Table of Contents order.

AlanDodson
New Contributor III

Unfortunately I'm getting an error on the line 'if lyr.name in List2:'

File "<string>" - AttributeError: 'str' object has no attribute 'name'

When I print List2 the entries are still "<layer u'September'>" or something like that so it's not matching List1 "September".  My List3 result is a list of lots of duplicates of items in List2 with the "<layer u'September'>" formatting.  

0 Kudos
PavanYadav
Occasional Contributor II

Did you try str(), like this:

    List2a.append(str(l.name))

?

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

This works for me:

>>> mxd = arcpy.mapping.MapDocument("CURRENT")
>>> df = mxd.activeDataFrame
>>> 
>>> List1 = ["September", "October", "November", "December"]
>>> List2 = [lyr.name for lyr in arcpy.mapping.ListLayers(mxd, data_frame=df)]
>>> List3 = list(set(List1).intersection(List2))
>>> List3
[u'September', u'December']
>>> 
AlanDodson
New Contributor III

This works for me, thanks so much.  If anyone else reading this requires a string it requires the following change:  On line 5 change [lyr.name for ....  to [str(lyr.name) for ....