Better way to do an UpdateCursor on several fields??

670
4
08-01-2012 04:46 PM
JoelThomas
New Contributor II
Hello - I am trying to query a field(type-double) called "STATUS" and where there are "0's in that field, I want to update another field called "HAZ_STATUS"(type-text). So this might not be the best method, not sure, but it works. My question is, if I had to do this for another 15 fields, would I have to insert this code 15 times, or is there a better method? Also, I would update "STATUS" directly, but the field type is "double", and I want to update it with "text". So creating a new field with a new field type is the only solution, right?

I appreciate any comments - I'm pretty new at this..

fldName6 = "HAZ_STATUS"
inFeatures = os.getcwd() + '\\''myMDB.mdb\\myFC'
query = '[STATUS] = 0'
rows = arcpy.UpdateCursor(inFeatures, query)
row = rows.next()
while row:
    row.setValue(fldName6, "No Violations")
    rows.UpdateRow(row)
    row = rows.next()
del row, rows
Tags (2)
0 Kudos
4 Replies
JohnCobb1
New Contributor
I'd just use IF statements. Row objects have the fields as attributes, so you can use row.FIELD to clarify your code.


inFeatures = os.getcwd() + '\\''myMDB.mdb\\myFC'

row = None
uc = arcpy.UpdateCursor(inFeatures):
for row in uc
    if row.STATUS == 0:
        row.HAZ_STATUS = "No Violations"
#    if row.OTHERFIELD == X:
#        row.HAZ_OTHER = 'Some Text'
    uc.updateRow(row)
del uc, row
0 Kudos
markdenil
Occasional Contributor III
You should use a query in the cursor definition only to resrict the rows in the cursor. Which ideed seems to be what you want to do in the situation that you report works.

What exactly you mean by "do this for another 15 fields", however, is not clear.
Do you want to set another 15 field values based on the the fact that [STATUS] = 0?
Or do you want to test another 15 fields beside [STATUS]?

If the first, you can just add lines setting the value of each field to the existing setValue,
then fire the updateRow.

If, as seems likely, you want the second option (to test 15 fields, and set some value accordingly), then:
Run the cursor on the whole table (no query)
test each of the items of interest in each row; if the condition is met, then set the value.
rows = arcpy.UpdateCursor(inFeatures)
row = rows.next()
while row:
    if row.STATUS == 0:
        row.setValue(fldName6, "No Violations")
    if row.OtherField == 1:
        row.setValue(fldName7, "Something")
#   other test here...
    rows.UpdateRow(row)
    row = rows.next()
 


Note that for Arc10 you should use
for row in rows:
intead of
row = rows.next()
while row:
    ....
    row = rows.next()


... and yes you need a text item to place text. One can place a number in a text field (and turn it back into a number when you take it out), but text just will not go in a numeric field.
Although you CAN put the ansi or ascii code value of a text character in a numeric field, but the question then becomes: why?
0 Kudos
ChristopherThompson
Occasional Contributor III
i think the part you'd need to repeat 15x would be

row.setValue(fldName6, "No Violations")


but for each field and updated information.  So you'd potentially have (fldName7,"New Value").. 15 lines of code inside your while loop if you were to do this outside of a loop.  If you're doing the same thing for each field (i.e. converting 0 values to some sort of text) you could create a list of the fields then iterate through those for each row that you're on. so something like the following might work:

rows = arcpy.UpdateCursor(inFeatures, query,'field_a;field_b;field_c... field_x')
field_list = ['field_a','field_b','field_c'...'field_x']
for row in rows:
    for field in field_list:
        field_x = 'row.' + field
        row.setValue(field_x, "No Violations")
        rows.UpdateRow(row)


This sort of thing gets more complicated of course depending on the number of different scenarios you have to handle, but you could work out a variety of if/else type statements to handle that sort of decision making.  And yes, if the field is currently a double but you need a text value you need to create a new text field to capture that.

One thing I'm not sure about in your code is the use of the while loop... maybe its a bit of preference but a 'for loop' might be more efficent, and it keeps you from having to call row.next so it simplifies your code a little bit.  My understanding is that 'while loops' are good for checking on whether a particular condition has changed, which isn't really what you're doing in this example.  The for loop simply steps through each row in your cursor, performing the actions you want on each row, then moving to the next row and repeating those actions..  until it reaches the end.  Ultimately, I'm not sure this is a significant issue - your code obviously is working, but might be something to consider, and a lot of this may depend on how many rows you are dealing with.
0 Kudos
JoelThomas
New Contributor II
Thanks for the 3 excellent responses. I was using the while loop when I was testing this in 9.3 - I didn't plan on changing it, but now I will that I can see the difference..thanks again!
0 Kudos