I have a dataset that contains a field with a range of numbers (e.g. 1, 2, 3-6) as well as other fields. I've used python to expand the range field into discrete numbers (e.g. 1, 2, 3, 4, 5, 6) stored in a list in python. I would like to insert rows (6 in this example) with the range values. The values from the other fields would be copied for each new row, for each row in the table.
Row Example
| A | 1, 2, 3-6 | xxa | xxb |
to
| A | 1 | xxa | xxb |
| A | 2 | xxa | xxb |
| A | 3 | xxa | xxb |
| A | 4 | xxa | xxb |
| A | 5 | xxa | xxb |
| A | 6 | xxa | xxb |
I have adapted the code written by @Aaron. The code below works for the first row, but I would like it to read every row in the input table. In other words, it is not advancing throughout the table. I think I need to add another for loop at the beginning of insert_rows().
# import libraries
import arcpy
import os
arcpy.env.overwriteOutput = True
tbl = arcpy.GetParameterAsText(0)
def extractit(str):
"""
Creates a list (e.g. [1,2,3,4,5,6] from string such as '1, 2, 3-6'
"""
parts = str.replace(" ", "").split(",")
numbers = []
for part in parts:
if '-' in part:
p = part.split("-")
numbers.extend(list(range(int(p[0]), int(p[1]) + 1)))
else:
numbers.append(int(part))
return numbers
def create_table(tbl):
"""
Creates a duplicate (but empty) table
because we do not want to alter the original
"""
arcpy.CreateTable_management(os.path.dirname(tbl), os.path.basename(tbl) + "_altered_v2", template=tbl)
arcpy.DeleteRows_management(tbl + "_altered_v2")
def insert_rows(tbl):
"""
Insert rows into new table
"""
# Get row value in original table
row = [row for row in arcpy.da.SearchCursor(tbl, ["MERIDIAN", "TOWNSHIP", "RANGE", "TOWNSHIP_D", "RANGE_D",
"SUBDIVIS", "NOTES_SU",
"BLMSERIA", "CATEGORY", "ACREAGE", "EXCLUSIO", "VILL_BLK",
"CONV_DAT", "IC_PAT_N", "ENCUMBRA"])][0]
numbers = extractit(row[5]) # Extract number field
cursor = arcpy.da.InsertCursor(tbl + "_altered_v2", ["MERIDIAN", "TOWNSHIP", "RANGE", "TOWNSHIP_D", "RANGE_D",
"SUBDIVIS", "NOTES_SU",
"BLMSERIA", "CATEGORY", "ACREAGE", "EXCLUSIO", "VILL_BLK",
"CONV_DAT", "IC_PAT_N", "ENCUMBRA"])
for number in numbers:
row_value = (row[0], row[1], row[2], row[3], row[4], str(number), row[6], row[7], row[8], row[9], row[10],
row[11], row[12], row[13], row[14])
cursor.insertRow(row_value)
# Delete cursor object
del cursor
if __name__ == '__main__':
create_table(tbl)
insert_rows(tbl)
1 Answer 1
Here is one approach. There are three main components:
extractit()
manipulates unruly strings such as'1, 2, 3-6'
create_fc()
creates a new featureclass so as not to alter the originalinsert_rows()
puts all the pieces together
import arcpy, os
fc = r'C:\temp\test.gdb\temp'
def extractit(str):
"""
Creates a list from string such as '1, 2, 3-6'
"""
parts = str.replace(" ", "").split(",")
numbers = []
for part in parts:
if '-' in part:
p = part.split("-")
numbers.extend(list(range(int(p[0]), int(p[1]) + 1)))
else:
numbers.append(int(part))
return numbers
def create_fc(fc):
# Create a new featureclass
arcpy.CreateFeatureclass_management(os.path.dirname(fc), os.path.basename(fc) + "_altered", template = fc, spatial_reference = fc)
# Delete Rows
arcpy.DeleteRows_management(fc + "_altered")
def insert_rows(fc):
# Get row value in original fc
rows =[row for row in arcpy.da.SearchCursor(fc, ["field1", "field2", "field3", "field4", "SHAPE@"])]
for row in rows:
numbers = extractit(row[1]) # Extract number field
cursor = arcpy.da.InsertCursor(fc + "_altered", ["field1", "field2", "field3", "field4", "SHAPE@"])
for number in numbers:
row_value = (row[0], str(number), row[2], row[3], row[4])
cursor.insertRow(row_value)
# Delete cursor object
del cursor
if __name__ == '__main__':
create_fc(fc)
insert_rows(fc)
Before
After
-
1Spectacular! There's a few very good pearls of wisdom in that code.Michael Stimson– Michael Stimson2019年03月14日 05:28:36 +00:00Commented Mar 14, 2019 at 5:28
for
loop.