If else statement

6815
63
Jump to solution
08-28-2013 04:39 AM
JamesSmith7
Emerging Contributor
I am modifying a script suggested in a prior thread.  http://forums.arcgis.com/threads/90242-Polygon-Centroid?highlight=jsmith0705

I want to be able to select a line, determine if the ARCLENGTH field has a value greater than zero, return that value if greater than zero, if not return the value from the Shape_Length field.

The script runs with no errors or results. 

import arcpy  mxd = arcpy.mapping.MapDocument ("CURRENT") df = arcpy.mapping.ListDataFrames (mxd)[0]  lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]  for lyr in arcpy.mapping.ListLayers(mxd):  tlyr = lyr  dsc = arcpy.Describe(tlyr)  sel_set = dsc.FIDSet  if dsc.shapeType == "Line":   if len(sel_set) > 0: #If ARCLENGTH value > 0           arcpy.AddMessage(str(ARCLENGTH)) #Return ARCLENGTH value   else:    arcpy.AddMessage(str(Shape_Length)) #Return Shape_Length value
Tags (2)
0 Kudos
63 Replies
JamesSmith7
Emerging Contributor
Richard,

Can you point me in the direction to read up on the OBJECTID IN operator?  It looks like I may need to select more than one Polyline at a time.

Thanks
0 Kudos
RichardFairhurst
MVP Alum
Richard,

Can you point me in the direction to read up on the OBJECTID IN operator?  It looks like I may need to select more than one Polyline at a time.

Thanks


ESRI has virtually nothing about it.  It's a simple expression.  All you need is the field name followed by the word IN and then a comma separated list of correctly typed values within a pair of parentheses.  I already gave several examples.  Any single value in the list that matches the value of the field for any given record will be included in the selection.  You would need to output the python list as a comma separated list in one string.  I believe this will work to convert a python list of numbers to a comma separated list:

myList = [12,34,56,78,90]
myString = ",".join(myList)

and then you could make the where clause using the appropriate field delimiters for your database:

'"OBJECTID" IN (' + myString + ')'

In the case of your latest code, I think that the dsc.fidSet is already a string so I think you can use replace to substitute semicolons with commas:

mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
    dsc = arcpy.Describe(lyr)
    sel_set = dsc.fidSet.replace(";",",")
    if dsc.shapeType == "Polyline":
        rows = arcpy.da.SearchCursor(lyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set + ")")
        for row in rows:
            arcLength = row.[1]
            shapeLength = row.[2]
            if arcLength > ' ':
                print arcLength
            else:
                print shapeLength
    del row, rows


I changed it to a da cursor, since performance is about 10 times faster or more than the old cursor style.  You would still need to replace the print methods with AddMessages and I indented the arcLength test so that each line feature will print.  The test also will handle single digit arcLength values now that I know it is a string field (although you probably don't have any single digit values in the field).
0 Kudos
JamesSmith7
Emerging Contributor
I was hoping ESRI or the forums contained attitional information.  I also have a book that covers Python and the OBJECTID IN operator is not mentioned.
0 Kudos
JakeSkinner
Esri Esteemed Contributor
James,

Here is tech article that discusses selecting multiple values:

http://support.esri.com/en/knowledgebase/techarticles/detail/32024

Try the below.  It should work whether you select one line or multiple lines:

mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
    dsc = arcpy.Describe(lyr)
    sel_set = dsc.fidSet
    if dsc.shapeType == "Polyline":
        if len(sel_set) > 1:
            sel_set = sel_set.replace(";", ",")
            arcLengthList = []
            shapeLengthList = []
            rows = arcpy.SearchCursor(lyr, "OBJECTID IN (" + sel_set + ")")
            for row in rows:            
                arcLengthList.append(row.ARCLENGTH)
                shapeLengthList.append(row.shape.length)
            i = 0
            while i < len(arcLengthList):
                if len(arcLengthList) > 1:
                    print arcLengthList
                else:
                    print shapeLengthList
                i += 1
        else:
            rows = arcpy.SearchCursor(lyr, "OBJECTID = " + sel_set)
            for row in rows:
                arcLength = row.ARCLENGTH
                shapeLength = row.shape.length
            if len(arcLength) > 1:
                print arcLength
            else:
                print shapeLength
    del row, rows
0 Kudos
RichardFairhurst
MVP Alum
James,

Here is tech article that discusses selecting multiple values:

http://support.esri.com/en/knowledgebase/techarticles/detail/32024

Try the below.  It should work whether you select one line or multiple lines:

mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
    dsc = arcpy.Describe(lyr)
    sel_set = dsc.fidSet
    if dsc.shapeType == "Polyline":
        if len(sel_set) > 1:
            sel_set = sel_set.replace(";", ",")
            arcLengthList = []
            shapeLengthList = []
            rows = arcpy.SearchCursor(lyr, "OBJECTID IN (" + sel_set + ")")
            for row in rows:            
                arcLengthList.append(row.ARCLENGTH)
                shapeLengthList.append(row.shape.length)
            i = 0
            while i < len(arcLengthList):
                if len(arcLengthList) > 1:
                    print arcLengthList
                else:
                    print shapeLengthList
                i += 1
        else:
            rows = arcpy.SearchCursor(lyr, "OBJECTID = " + sel_set)
            for row in rows:
                arcLength = row.ARCLENGTH
                shapeLength = row.shape.length
            if len(arcLength) > ' ':
                print arcLength
            else:
                print shapeLength
    del row, rows


ArcLength  is a string field with spaces, so the test will fail unless it converts the string to a number and tests for a space.  IN works even if there are no listed object (nothing is selected but no error occurs), a single item, or a list of items, so the else clause is not necessary.  = fails and produces an error if there is no listed objectID value or a list, so IN is all you need.
0 Kudos
RichardFairhurst
MVP Alum
I was hoping ESRI or the forums contained attitional information.  I also have a book that covers Python and the OBJECTID IN operator is not mentioned.


The IN operatot is not a python expression.  It is an SQL expression and it is fine to use with all of the databases and the only efficient way to work with lists of values in SQL.  It is also fine to use with Python lists, since Python code that uses the IN expression will be found all over the Python forum by every advanced user of Python here.  So ignore that recommendation for both SQL and Python.  So use the IN operator as shown in my example or Jakes example (as corrected by me for the arcLength field test) and you will get the idea soon enough about what it does.
0 Kudos
JamesSmith7
Emerging Contributor
ArcLength  is a string field with spaces, so the test will fail unless it converts the string to a number and tests for a space.  IN works even if there are no listed object (nothing is selected but no error occurs), a single item, or a list of items, so the else clause is not necessary.  = fails and produces an error if there is no listed objectID value or a list, so IN is all you need.


Richard,

Which statement accounts for the ARCLENGTH field being a string with spaces?  Because, if I use your example, I run into a RuntimeError: A column was specified that does not exist, in line 15.  for row in rows:, but the error is probably in line 14, the SearchCursor.

import arcpy

mxd = arcpy.mapping.MapDocument ("CURRENT") 
df = arcpy.mapping.ListDataFrames (mxd)[0] 
lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]
arcpy.AddMessage(lyr.name)

for lyr in arcpy.mapping.ListLayers(mxd):
 dsc = arcpy.Describe(lyr)
 sel_set = dsc.fidSet
 myString = ",".join(sel_set)
 rows = arcpy.da.SearchCursor(lyr, ["OID@", "ARCLENGTH", "Shape_Length"], "OBJECTID IN (" + myString + ")")
 for row in rows:
  arcLength = row.ARCLENGTH
  shapeLength = row.Shape_Length
  if len(arcLength) > 0:
   arcpy.AddMessage("ArcLength = " + arcLength)
  else:
   arcpy.AddMessage("ShapeLength = " + str(shapeLength))
  del row, rows
0 Kudos
JamesSmith7
Emerging Contributor
ArcLength  is a string field with spaces, so the test will fail unless it converts the string to a number and tests for a space.  IN works even if there are no listed object (nothing is selected but no error occurs), a single item, or a list of items, so the else clause is not necessary.  = fails and produces an error if there is no listed objectID value or a list, so IN is all you need.


I am receiving an error in line 66, del row, rows.  The error code is an NameError: name row and rows are not defined.  How are they not defined?  If I comment the del row, rows statement out the script runs, but without errors or results. 

import arcpy

mxd = arcpy.mapping.MapDocument ("CURRENT") 
df = arcpy.mapping.ListDataFrames (mxd)[0] 
lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]
arcpy.AddMessage(lyr.name)
for lyr in arcpy.mapping.ListLayers(mxd):
 dsc = arcpy.Describe(lyr)
 sel_set = dsc.fidSet
 if dsc.shapeType == "Polyline":
  if len(sel_set) > 0:
   sel_set = sel_set.replace(";", ",")
   arcLengthList = []
   shapeLengthList = []
   rows = arcpy.SearchCursor(lyr, "OBJECTID IN (" + sel_set + ")")
   for row in rows:            
    arcLengthList.append(row.ARCLENGTH)
    shapeLengthList.append(row.Shape_Length)
   i = 0
   while i < len(arcLengthList):
    if len(arcLengthList) > 0:
     print arcLengthList
    else:
     print shapeLengthList
    i += 1
    arcpy.AddMessage("Good")
  else:
   rows = arcpy.SearchCursor(lyr, "OBJECTID = " + sel_set)
   for row in rows:
    arcLength = row.ARCLENGTH
    shapeLength = row.Shape_Length
   if len(arcLength) > ' ':
    arcpy.AddMessage("ArcLength = " + arcLength)
   else:
    arcpy.AddMessage("ShapeLength = " + str(shapeLength))
 del row, rows
0 Kudos
RichardFairhurst
MVP Alum
I am receiving an error in line 66, del row, rows.  The error code is an NameError: name row and rows are not defined.  How are they not defined?  If I comment the del row, rows statement out the script runs.

import arcpy

mxd = arcpy.mapping.MapDocument ("CURRENT") 
df = arcpy.mapping.ListDataFrames (mxd)[0] 
lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]
arcpy.AddMessage(lyr.name)
for lyr in arcpy.mapping.ListLayers(mxd):
 dsc = arcpy.Describe(lyr)
 sel_set = dsc.fidSet
 if dsc.shapeType == "Polyline":
  if len(sel_set) > 0:
   sel_set = sel_set.replace(";", ",")
   arcLengthList = []
   shapeLengthList = []
   rows = arcpy.SearchCursor(lyr, "OBJECTID IN (" + sel_set + ")")
   for row in rows:            
    arcLengthList.append(row.ARCLENGTH)
    shapeLengthList.append(row.Shape_Length)
   i = 0
   while i < len(arcLengthList):
    if len(arcLengthList) > 0:
     print arcLengthList
    else:
     print shapeLengthList
    i += 1
    arcpy.AddMessage("Good")
  else:
   rows = arcpy.SearchCursor(lyr, "OBJECTID = " + sel_set)
   for row in rows:
    arcLength = row.ARCLENGTH
    shapeLength = row.Shape_Length
   if len(arcLength) > ' ':
    arcpy.AddMessage("ArcLength = " + arcLength)
   else:
    arcpy.AddMessage("ShapeLength = " + str(shapeLength))
  del row, rows


Just indent the del row, rows one more time and that will fix that line.  It is at the wrong indent level.
0 Kudos
JamesSmith7
Emerging Contributor
Just indent the del row, rows one more time and that will fix that line.  It is at the wrong indent level.


I would have expected an indentation error, but not the name error.  Thanks.
0 Kudos