Select to view content in your preferred language

Update Cursor multiple nested If Elif Else

1672
9
12-09-2022 03:01 PM
CCWeedcontrol
Frequent Contributor

I have a table that I need to do multiple nested if else it appears that only the last if else is used and field only gets populated with 15, there are some that meet the 25,35 and 45 but they don't get updated.

what am I doing wrong?

where = "AppType = 'SFR Active'"
with arcpy.da.UpdateCursor(table1, ["Field1","Field12","Field3","Field4","Field5", "Field6", "Field7","Field8"], where) as cursor:
    for row in cursor:
        #if row[0] is None:
            #continue
        if row[0] == "Approved" and row[1] == "Approved" and row[2] == "Approved" and row[3] is not None and row[4] == "Pass":
            row[7] = 15
        else:
            row[7] = 0

            
        if row[3] == "In_1" and row[4] == "Pass":
            row[7] = 25
        else:
            row[7] = 15
  
       
        if row[3] == "In_2" and row[4] == "Pass":
            row[7] = 35
        else:
            row[7] = 25

        
        if row[3] == "In_3" and row[4] == "Pass":
            row[7] = 45
        else:
            row[7] = 35


        
        cursor.updateRow(row)

 

 

0 Kudos
9 Replies
BlakeTerhune
MVP Regular Contributor

Try adding some print statements to help you debug. In your else, print row[3] and row[4] so you can see what values it's actually getting.

0 Kudos
CCWeedcontrol
Frequent Contributor

Good, call. I am seeing the the prints now.

0 Kudos
DanPatterson
MVP Esteemed Contributor

Your code won't cover all cases I suspect, but what you have is muddled a bit...

for row in cursor:
    if row[0] == "Approved" and row[1] == "Approved" and row[2] == "Approved":
		if row[3] == "In_1":
    		if row[4] == "Pass":
			    row[7] = 25
			else:
				row[7] = 15
		elif row[3] == "In_2":
		    if row[4] == "Pass":
			    row[7] = 35
			else:
				row[7] = 25
		elif row[3] == "In_3":
		    if row[4] == "Pass":
			    row[7] = 45
			else:
			    row[7] = 35
	    elif row[3] is not None:
  		    if row[4] == "Pass":
			    row[7] = 15
			else:
			    row[7] = 9
    else:
	    ???????????????

You will have to decide what to do if none of the remaining cases aren't met.

You would be better off constructing all possible combinations and using a dictionary to return what you want to use for the two remaining fields.


... sort of retired...
CCWeedcontrol
Frequent Contributor

Thank you for the visual of formatting the if, elf and else.

Line 24 would just be "Pass", so i can continue.

0 Kudos
by Anonymous User
Not applicable

Just another version using Dan's dictionary suggestion: 

valDict = {"In_1": 25, "In_2": 35, "In_3": 45, ...}

with arcpy.da.UpdateCursor(table1, ["Field1", "Field12", "Field3", "Field4", "Field5", "Field6", "Field7", "Field8"],
                           where) as cursor:
    for row in cursor:
        # if row[0] is None:
        # continue
        if all([row[0] == "Approved", row[1] == "Approved", row[2] == "Approved", row[3] is not None, row[4] == "Pass"]):
            row[7] = 15 
        else: 
            row[7] = valDict.get(row[3]) if row[4] == "Pass" else valDict.get(row[3], 10) - 10

This will point out which In_i values are not in the dictionary by assigning them 0, or subtract the 10 if row[4] does not equal 'Pass' for that row.

0 Kudos
CCWeedcontrol
Frequent Contributor

Interesting, I will have to try to use the dictionary option.

0 Kudos
CCWeedcontrol
Frequent Contributor

Jeffk,

I was trying to impalement your suggestion but I am having trouble getting the code to work.

Hopefully I can explain it correctly, I would really appreciate the help to understand dictionaries in this type of situations.

If reviews 1-4 equal approved then, progress filed = 15%, if three out of the four review are pass then Progress field = 0%

If Reviews1-4 fields = Approved & Event field = Foundation or Setback or Shear Panel 1 & EventRes1 field = Pass, then Progress field = 15%, if if Reviews1-4 = Approved & Event field = Foundation or Setback or Shear Panel 1 & EventRes1 field = Needs corrections or In progress or partial Pass or Cancelled, then progress field = 15%

if If Reviews1-4 fields = Approved & Event field = Framing or BC- Framing & EventRes1 field = Pass, then Progress field = 50%, if If Reviews1-4 fields = Approved & Event field = Framing or BC- Framing & EventRes1 field = Needs corrections or In progress or partial Pass or Cancelled, then progress, then progress field = 25%

if If Reviews1-4 fields = Approved & Event field = Insulation or Stucco & EventRes1 field = Pass, then Progress field = 75%, if If Reviews1-4 fields = Approved & Event field = Insulation & EventRes1 field = Needs corrections or In progress or partial Pass or Cancelled, then progress, then progress field = 50%

 

if If Reviews1-4 fields = Approved & Event field = Final & EventRes1 field = Pass, then Progress field = 100%, if If Reviews1-4 fields = Approved & Event field = Final & EventRes1 field = Needs corrections or In progress or partial Pass or Cancelled, then progress, then progress field = 75%

If both fields "Certif", "CertifDate" are populated , then Progress = 100%

 

Some fields are blank.

 

0 Kudos
by Anonymous User
Not applicable

Haven't had time to try to digest this yet...  I think it would help if you break this down a little further though since the mixing of 'if if', &, =, and 'then' makes it kind of hard to follow.  I'd suggest to write these as if statements, so it will show what you are comparing as a conditional and what is done if it is met.

0 Kudos
BlakeTerhune
MVP Regular Contributor

@CCWeedcontrol, there are some gaps in the explanation of your logic there, but here's another take on evaluating your progress field. I organized evaluation of the larger groups separately to make the evaluation of the progress field a little easier to follow. Please correct as needed to clarify logic gaps.

 

# Get arcpy.da cursor rows back as dictionary with field names
# https://arcpy.wordpress.com/2012/07/12/getting-arcpy-da-rows-back-as-dictionaries/
def rows_as_dicts(cursor):
    colnames = cursor.fields
    for row in cursor:
        yield dict(zip(colnames, row))


fields = [
    "reviewField1",
    "reviewField12",
    "reviewField3",
    "reviewField4",
    "EventField",
    "EventRes1",
    "Certif",
    "CertifDate",
    "ProgressFiledField"
]
where = "AppType = 'SFR Active'"
with arcpy.da.UpdateCursor(table1, fields, where) as cursor:
    for row in rows_as_dicts(cursor):
        # Evaluate Review fields
        review_approved_count = [
            row["reviewField1"],
            row["reviewField12"],
            row["reviewField3"],
            row["reviewField4"]
        ].count("Approved")

        # Evaluate Event
        eventField = row["EventField"]
        if eventField in ["Foundation", "Setback", "Shear Panel 1"]:
            event_state = "Foundation"
        elif eventField in ["Framing" or "BC- Framing"]:
            event_state = "Framing"
        elif eventField in ["Insulation" or "Stucco"]:
            event_state = "Insulation"
        elif eventField in ["Final"]:
            event_state = "Final"
        else:
            raise Exception(f"EventField value {eventField} not handled.")

        # Evaluate eventRes1
        eventRes1 = row["EventRes1"]
        if eventRes1 in ["Needs corrections", "In progress", "partial Pass", "Cancelled"]:
            eventRes1_state = "Not Passed"
        elif eventRes1 == "Pass":
            eventRes1_state = "Pass"
        else:
            raise Exception(f"EventRes1 value {eventRes1} not handled.")

        # Evaluate Progress
        progress_filed = row["ProgressFiledField"]
        if review_approved_count == 4:
            if event_state == "Foundation":
                # Doesn't matter what EventRes1 is?
                progress_filed = "15%"
            elif event_state == "Framing":
                if eventRes1_state == "Passed":
                    progress_filed = "50%"
                else:
                    # eventRes1 not passed
                    progress_filed = "25%"
            elif event_state == "Insulation":
                if eventRes1_state == "Passed":
                    progress_filed = "75%"
                else:
                    # eventRes1 not passed
                    progress_filed = "50%"
            elif event_state == "Final":
                if eventRes1_state == "Passed":
                    progress_filed = "100%"
                else:
                    # eventRes1 not passed
                    progress_filed = "75%"
        else:
            # review_approved_count < 4 and
            # doesn't matter what EventField or EventRes1 are.
            progress_filed = "0%"

        # These dates override all other logic evaluations?
        if row["Certif"] and row["CertifDate"]:
            progress_filed = "100%"

        # Update row with progress.
        row["ProgressFiledField"] = progress_filed
        row_values = list(row.values())
        cursor.updateRow(row_values)