Removing/Replacing specific characters from a field

1299
10
Jump to solution
10-31-2018 03:54 PM
GIS_geek
New Contributor III

I am trying to remove specific characters from a field called CCTV_SLID.  The field I am working with looks like this CLMH123W456MH123W455, STMH123W457, SIMH123W458, SYMH123W459.  I am trying to remove the prefixes which are CL, ST, SI, and SY.  I have the following script and get a IOError: "C" does not exist error. Any help would be appreciated. Thanks.

# Remove prefix from CCTV_SLID


fcLst = "C:/Desktop/CCTV.gdb/GravityMain"
for fc in fcLst:
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
        with arcpy.da.UpdateCurson(fc, fieldList) as cursor:
            for row in cursor:
                for i in range(len(fieldList)):
                    row = row.replace("CL"," ")
                    cursor.updateRow(row)

0 Kudos
1 Solution

Accepted Solutions
curtvprice
MVP Esteemed Contributor

Here's my preferred approach (which Joe mentioned).

In Python some times it is easier to just let an error happen instead of coding a check for every possible thing that can go wrong (in your case, that the text field has a null value).

I also fixed this so it will only remove the prefix, that is, your prefix must be the first two chars of the text field value.

import arcpy

print("Replace and remove prefix from any and all text fields.")
fcLst = ["C:/Desktop/CCTV.gdb/GravityMain"]
for fc in fcLst:
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
        with arcpy.da.UpdateCursor(fc, fieldList) as cursor:
            for row in cursor:
                for i in range(len(fieldList)):
                    try:
                        if row[i][:2] in ["CL", "ST", "SI","SY"]:
                            row[i] = row[i][2:]
                            cursor.updateRow(row)
                    except:
                        pass
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

10 Replies
DanPatterson_Retired
MVP Emeritus

/blogs/dan_patterson/2016/08/14/script-formatting  would really help because line numbers can be referred to

GIS_geek
New Contributor III
import arcpy

# Remove prefix from CCTV_SLID
print("Replace and remove prefix from CCTV_SLID.")
fcLst = "C:/Desktop/CCTV.gdb/GravityMain"
for fc in fcLst:
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
        with arcpy.da.UpdateCursor(fc, fieldList) as cursor:
            for row in cursor:
                for i in range(len(fieldList)):
                    row[i] = row[i].replace("CL"," ")
                    cursor.updateRow(row)
0 Kudos
curtvprice
MVP Esteemed Contributor

Here's my preferred approach (which Joe mentioned).

In Python some times it is easier to just let an error happen instead of coding a check for every possible thing that can go wrong (in your case, that the text field has a null value).

I also fixed this so it will only remove the prefix, that is, your prefix must be the first two chars of the text field value.

import arcpy

print("Replace and remove prefix from any and all text fields.")
fcLst = ["C:/Desktop/CCTV.gdb/GravityMain"]
for fc in fcLst:
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
        with arcpy.da.UpdateCursor(fc, fieldList) as cursor:
            for row in cursor:
                for i in range(len(fieldList)):
                    try:
                        if row[i][:2] in ["CL", "ST", "SI","SY"]:
                            row[i] = row[i][2:]
                            cursor.updateRow(row)
                    except:
                        pass
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JoshuaBixby
MVP Esteemed Contributor

I suggest out-denting your cursor update call, Line #13, by one level.  You can wait until you have updated the entire row before committing it.

curtvprice
MVP Esteemed Contributor

Joshua, you are so right. Unnecessarily calling an update could massively slow things down. Here's a fix that outdents it even more so only one update would be called, and only if a change was made:

import arcpy

print("Replace and remove prefix from any and all text fields.")
fcLst = ["C:/Desktop/CCTV.gdb/GravityMain"]
for fc in fcLst:
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
        with arcpy.da.UpdateCursor(fc, fieldList) as cursor:
            for row in cursor:
                rowmod = False
                for i in range(len(fieldList)):
                    try:
                        if row[i][:2] in ["CL", "ST", "SI","SY"]:
                            row[i] = row[i][2:]
                            rowmod = True
                    except:
                        pass
                if rowmod:
                    cursor.updateRow(row)
DanPatterson_Retired
MVP Emeritus
 fcLst = "C:/Desktop/CCTV.gdb/GravityMain"
for fc in fcLst:
    print(fc)
    
C
:
/
D
e
s

...... snip .......

you don't have a list for the fcList

you want

fcLst = ["C:/Desktop/CCTV.gdb/GravityMain"]
for fc in fcLst:
    print(fc)
    
C:/Desktop/CCTV.gdb/GravityMain
GIS_geek
New Contributor III

Dan,

I updated the script and I get the following error

      row = row.replace("CL","")
AttributeError: 'NoneType' object has no attribute 'replace'

0 Kudos
JoeBorgione
MVP Emeritus

None means your value for row is null.  You'll need to 'trap' for that condition with an if conditional or a try/except block.

That should just about do it....
DanPatterson_Retired
MVP Emeritus
if row is not None:
    Do the work here
if row[i] not in (None, "", "anything else you want to check for"):
    Do good stuff here