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?
Solved! Go to Solution.
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']
>>>
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))
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))
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)
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?
List3 should be in the List2 (or ListLayers) order. It is likely that it would match the Table of Contents order.
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.
Did you try str(), like this:
List2a.append(str(l.name))
?
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']
>>>
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 ....