how to sort a ListLayers list?

6168
10
Jump to solution
06-21-2013 07:32 AM
JasonMills
New Contributor III
I get a list of layers from ArcMap. If I sort the layer list, it doesn't seem to sort. Here's a snippet of the code I use.
I attached a text file showing the results when I run the script from the python window in ArcMap. I also attached an image showing my table of contents with 219 layers.
When I use the code in a script, the results are a lot worst then the results show.
I'm using 10.1, sp1 on XP.

mxd = arcpy.mapping.MapDocument("CURRENT")
dfList = arcpy.mapping.ListDataFrames(mxd,"*")
df = dfList[0]
layerList = arcpy.mapping.ListLayers(mxd)
layerList.sort()
print str(len(layerList))
#print layerList
for layer in layerList:
    print layer.name
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable
Original User: curtvprice

Yeah, the layer name works great. Unless I'm using the layer name in my script logic. And someone happens to change the layer name. And my script can't see that unless it looks at the dataset name. Which is in the layer object. Which is why I wanted to sort the list of layers and not just a list of names.


Quite right. I found a neat and very fast way to do this, along those lines. Probably pretty equivalent to what you did using sortedDictValues:

lyrNames = sorted([x.name for x in lyrs]) d = dict((x.name, x) for x in lyrs) lyrsSorted = [d for i in lyrNames]

View solution in original post

0 Kudos
10 Replies
by Anonymous User
Not applicable
Original User: JSkinn3

Hi Jason,

Try appending the layer names to a list, and then sorting that list.  Ex:

mxd = arcpy.mapping.MapDocument("CURRENT")
dfList = arcpy.mapping.ListDataFrames(mxd,"*")
df = dfList[0]
layerList = arcpy.mapping.ListLayers(mxd)
list = []
for layer in layerList:
    list.append(layer.name)
list.sort()
for lyr in list:
    print lyr
0 Kudos
JasonMills
New Contributor III
Hi Jason,

Try appending the layer names to a list, and then sorting that list.  Ex:



That sorted the list of names correctly.
One of my scripts calculates a couple of fields in all of the mine layers. While it doesn't matter if the list is sorted or not, it would be nice to see where how far along the script is.
Also, why doesn't it sort correctly?
0 Kudos
by Anonymous User
Not applicable
Original User: curtvprice

why doesn't it sort correctly?


ListLayers() returns a list of layer objects, not just strings. Jake's excellent example showed how you extract the names into a list of strings so you can sort them.

The distinction between the objects and generic strings is a bit subtle, as the layer object has a method under the hood associated with it that, when you convert it to a string (say "print lyr"), returns the layer name. And when tools are provided a string as a layer argument, the arcpy uses the string to locate the layer object, and passes the layer the tool for you.
0 Kudos
JasonMills
New Contributor III
ListLayers() returns a list of layer objects, not just strings. Jake's excellent example showed how you extract the names into a list of strings so you can sort them.

The distinction between the objects and generic strings is a bit subtle, as the object has code associated with it that when you convert it to a string (say "print lyr") it will display the layer name. And when tools are provided a string, as a layer argument, the system locates the layer object based on its name and converts it for you.


So, there's really not an easy way to sort the list? I need to process the layers, not the name.
0 Kudos
by Anonymous User
Not applicable
Original User: curtvprice

So, there's really not an easy way to sort the list? I need to process the layers, not the name.


You could do this using a bit of complex code, but you don't need to because in arcpy you access the layers by name. So a sorted list of name strings works, as I think you already discovered.
0 Kudos
JasonMills
New Contributor III
You could do this using a bit of complex code, but you don't need to because in arcpy you access the layers by name. So a sorted list of name strings works, as I think you already discovered.


Yeah, the layer name works great. Unless I'm using the layer name in my script logic. And someone happens to change the layer name. And my script can't see that unless it looks at the dataset name. Which is in the layer object. Which is why I wanted to sort the list of layers and not just a list of names.
This is what I ended up with.
def sortedDictValues(adict):
    keys = adict.keys()
    keys.sort()
    return map(adict.get, keys)

mxd = arcpy.mapping.MapDocument("CURRENT")
dfList = arcpy.mapping.ListDataFrames(mxd,"*")
df = dfList[0]
layerList = arcpy.mapping.ListLayers(mxd)
layerDict = {}
print str(len(layerList))
#print layerList
for layer in layerList:
   layerDict[layer.name] = layer
sortedList = sortedDictValues(layerDict)
0 Kudos
by Anonymous User
Not applicable
Original User: curtvprice

Yeah, the layer name works great. Unless I'm using the layer name in my script logic. And someone happens to change the layer name. And my script can't see that unless it looks at the dataset name. Which is in the layer object. Which is why I wanted to sort the list of layers and not just a list of names.


Quite right. I found a neat and very fast way to do this, along those lines. Probably pretty equivalent to what you did using sortedDictValues:

lyrNames = sorted([x.name for x in lyrs]) d = dict((x.name, x) for x in lyrs) lyrsSorted = [d for i in lyrNames]
0 Kudos
JasonMills
New Contributor III
Quite right. I found a neat and very fast way to do this, along those lines. Probably pretty equivalent to what you did using sortedDictValues:

lyrNames = sorted([x.name for x in lyrs])
d = dict((x.name, x) for x in lyrs)
lyrsSorted = [d for i in lyrNames]


That's great! I like that better than having another function.
0 Kudos
by Anonymous User
Not applicable
Original User: curtvprice

Here's an even better one, from stackoverflow. Finally an example of the use of lambda that makes sense to me!

# in place
lyrs.sort(key=lambda x: x.name, reverse=False)
# make a new list
lyrs_sort = sorted(lyrs, key=lambda x: x.name, reverse=False)
0 Kudos