Android 多行求和:请求代码缩短

Android Multi-row summation: Request for code shortening

我有一个有 15 行的 table。每行有三列和一个总计列。我想获得每行的总数、总计和总体平均值。

用户可能不会为所有行输入数据,并且用户可能会跳过一行。

所以代码检查用户是否在每行的三个字段之一中输入了数据。

  1. 如果该行为空,则忽略它。
  2. 如果某些字段已填满,请告诉用户填写该行的其余部分。
  3. 如果一行中的所有字段都已填满,则对其所有字段求和并增加分隔符。

为简洁起见,我只粘贴了第 1 行和第 2 行的代码,但它显示了我要实现的目标的要点:

代码:

var a1 = 0
var a2 = 0
var total = 0
var divider = 0


// Row 1
if (b1p1.text.isNotEmpty() or b2p1.text.isNotEmpty() or b3p1.text.isNotEmpty()) {
    var y = 0
    listOf(b1p1, b2p1, b3p1).forEach {
        if (it.text.isEmpty()) {
            it.error = "Fill up empty fields!"
            y = 1
        }
    }

    if (y == 0) {
        divider++
        listOf(b1p1, b2p1, b3p1).forEach {
            a1 += it.text.toString().toInt()
        }
        total1.text = a1.toString()
        total += a1
        e2 = 1
    } else {
        Toast.makeText(activity, "Error", Toast.LENGTH_SHORT).show()
    }
}

// Row 2
if (b1p2.text.isNotEmpty() or b2p2.text.isNotEmpty() or b3p2.text.isNotEmpty()) {
    var y = 0
    listOf(b1p2, b2p2, b3p2).forEach {
        if (it.text.isEmpty()) {
            it.error = "Fill up empty fields!"
            y = 1
        }
    }

    if (y == 0) {
        divider++
        listOf(b1p2, b2p2, b3p2).forEach {
            a2 += it.text.toString().toInt()
        }
        total2.text = a2.toString()
        total += a2
    } else {

        Toast.makeText(activity, "Error", Toast.LENGTH_SHORT).show()
    }
}

if (e2 == 1) {

    grandTotalTextView.text = total.toString()

    average = total.toDouble()/divider

    val decimalFormatter = DecimalFormat("#,###.##")

    averageTextView.text = decimalFormatter.format(average).toString()

    cyeSingleton.anct3b = decimalFormatter.format(average).toString()

} else {

    Toast.makeText(activity, "Error 2", Toast.LENGTH_SHORT).show()
}

table:

这是我能想到的最好的。如果没有其他建议,我就这样吧。

提前致谢!

**编辑:感谢** https://whosebug.com/users/3736955/jemshit-iskenderov

data class TotalResult(val divider:Int, val allTotal:Int, val showError:Boolean)

private fun calculateTotalResult(allTextViews:List<List<TextView>>, totalTextViews:List<TextView>): TotalResult {
    var divider = 0
    var allTotal = 0
    var showError=false

    allTextViews.forEachIndexed{index, rowTextViews->
        val rowResult = calculateRowResult(rowTextViews as List<EditText>, totalTextViews[index])
        if(!rowResult.ignoreRow){
            if(rowResult.allFieldsFilled){
                divider+=1
                allTotal+=rowResult.rowTotal
            }else{
                showError = true
            }
        }
    }

    Toast.makeText(
        activity,
        "$divider, $allTotal, $showError", Toast.LENGTH_SHORT)
        .show()

    return TotalResult(divider, allTotal, showError)

}

data class RowResult(val ignoreRow:Boolean, val allFieldsFilled:Boolean, val rowTotal:Int)

private fun calculateRowResult(rowTextViews:List<EditText>, totalTextView:TextView): RowResult {
    val ignore = rowTextViews.filter{it.text.isBlank()}.count() == rowTextViews.size
    if(ignore)
        return RowResult(true, false, 0)

    var emptyFieldCount = 0
    var total = 0
    rowTextViews.forEach {textView ->
        if (textView.text.isEmpty()) {
            textView.error = "Fill up empty fields!"
            emptyFieldCount +=1
        }else{
            val fieldValue:Int? = textView.text.toString().toIntOrNull() // or toIntOrElse{0}
            if(fieldValue!=null) total+=fieldValue
        }
    }

    if(emptyFieldCount==0)
        totalTextView.text = total.toString()

    return RowResult(false, emptyFieldCount==0, total)
}
fun main(){
  val totalResult = calculateTotalResult(
    allTextViews = listOf(
        listOf(t11,t12,t13),
        listOf(t21,t22,t23)
    ),
    totalTextViews = listOf(totalView1, totalView2)
  )

  // single Toast error
  if(totalResult.showError){
      // showToast(error)
  }

  // use totalResult.divider, totalResult.allTotal
}

data class TotalResult(val divider:Int, val allTotal:Int, val showError:Boolean)

fun calculateTotalResult(allTextViews:List<List<TextView>>, totalTextViews:List<TextView>){
  var divider = 0
  var allTotal = 0
  var showError=false

  allTextViews.forEachIndexed{index, rowTextViews->
      val rowResult = calculateRowResult(rowTextViews, totalTextViews[index])
      if(!rowResult.ignore){
        if(rowResult.allFieldsFilled){
            divider+=1
            allTotal+=rowResult.rowTotal
        }else{
            showError = true
        }
      }
  }

  return TotalResult(divider, allTotal, showError)
}

data class RowResult(val ignoreRow:Boolean, val allFieldsFilled:Boolean, val rowTotal:Int)

fun calculateRowResult(rowTextViews:List<TextView>, totalTextView:TextView): RowResult {
    val ignore = rowTextViews.filter{it.isBlank()}.count() == rowTextViews.size
    if(ignore)
      return RowResult(true, false, 0)

    var emptyFieldCount = 0
    var total = 0
    rowTextViews.forEach {textView ->
        if (textView.text.isEmpty()) {
            textView.error = "Fill up empty fields!"
            emptyFieldCount +=1
        }else{
            val fieldValue:Int? = textView.text.toString().toIntOrNull() // or toIntOrElse{0}
            if(fieldValue!=null) total+=fieldValue
        }
    }

    if(emptyFieldCount==0)
      totalTextView.text = total.toString()

    return RowResult(false, emptyFieldCount==0, total)
}

提取了 calculateTotalResult()calculateRowResult(),因此多行和多列不需要重复相同的代码。

calculateRowResult() 处理单行 TextView。我不得不迭代 rowTextViews 两次,一次计算忽略,另一次如果不忽略则在 TextView 上显示错误。我们还没有在这里显示吐司错误。

calculateTotalResult() 遍历所有行并获得总结果。在此步骤后,我们仅显示一个 Toast 错误(如果需要)。

代码为伪代码,未经测试