问题描述
这是我的问题的样本数据,
List<EMPINSURED> lstempIns = new List<EMPINSURED>{
new EMPINSURED{ EmpID = 558,TOTAL_INSURED_AMT = 50000},new EMPINSURED{ EmpID = 559,TOTAL_INSURED_AMT = 75000}
};
List<EMP_ROUTINE_CHECKUP_HISTORY> lstempRoutineChkHist = new List<EMP_ROUTINE_CHECKUP_HISTORY>{
new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 1,EmpID = 558,ROUTINE_CHECKUP = 1,CHECK_UP_CHARGE = 20000},new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 2,EmpID = 559,CHECK_UP_CHARGE = 35000},new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 3,ROUTINE_CHECKUP = 2,CHECK_UP_CHARGE = 10000},new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 4,new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 5,ROUTINE_CHECKUP = 3,CHECK_UP_CHARGE = 20000}
};
一年中,仅允许员工进行三次例行检查。员工进行例行检查时,必须从总保险金额中扣除其检查费用。对于下一次例行检查,将仅向雇员支付保险总额中剩余金额的检查费用,超过此限额的任何费用,公司将不承担。
因此,用于计算REMAINING AMOUNT
的逻辑有点像这样::
int var = 0;
if(ROUTINE_CHECKUP == 1)
{
REMAINING_AMOUNT = TOTAL_INSURED_AMT - CHECK_UP_CHARGE;
var = CHECK_UP_CHARGE;
}
else if (ROUTINE_CHECKUP == 2)
{
REMAINING_AMOUNT = TOTAL_INSURED_AMT - (CHECK_UP_CHARGE + var);
var = CHECK_UP_CHARGE + var;
}
else if (ROUTINE_CHECKUP == 3)
{
REMAINING_AMOUNT = TOTAL_INSURED_AMT - (CHECK_UP_CHARGE + var);
var = CHECK_UP_CHARGE + var;
}
如何使用此逻辑开发LINQ查询以获取以下报告数据,否则可能会有更好的方法。 请参阅附件中的报告格式图像。
解决方法
使用一些private void flipCoin() {
final Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher_background);
final ImageView iv = ((ImageView) findViewById(R.id.imageView));
iv.setRotationY(0f);
//iv.animate().setDuration(10);
iv.animate().rotationY(90f).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
iv.setImageDrawable(drawable);
iv.setRotationY(270f);
iv.animate().rotationY(360f).setListener(null);
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
扩展方法,您可以将System.Linq
字段中的Join
列表与lstEmpIns
列表中的lstEmpRoutineChkHist
列表EmpId
转换为具有值,然后使用RoutineCheckup
通过OrderBy
对结果进行排序。
丑陋的部分是确定RemainingBalance
,因为我们必须查找RoutineCheckup
小于或等于当前项目的该员工的所有记录,然后将{{1 }},因此我们可以从CheckupCharge
中扣除它。可能有更好的方法,但这就是我想出的。
以下是基于您的代码但使用现代命名约定的示例:
RemainingBalance
一些用于生成输出的代码:
var results = empInsureds
.Join(empRoutineCheckupHistories,emp => emp.EmpId,hist => hist.EmpId,(emp,hist) => new
{
emp.EmpId,emp.TotalInsuredAmt,hist.RoutineCheckup,hist.CheckupCharge,RemainingBalance =
emp.TotalInsuredAmt -
empRoutineCheckupHistories
.Where(h => h.EmpId == hist.EmpId &&
h.RoutineCheckup <= hist.RoutineCheckup)
.Sum(h => h.CheckupCharge)
})
.OrderBy(r => r.RoutineCheckup)
.ToList();
其中使用了辅助功能:
Console.WindowWidth = 81;
Console.WriteLine(GetRow("EmpID","Total Insured Amt","Routine Checkup","Checkup Charge","Remaining Amount"));
Console.WriteLine(new string('-',80));
results.ForEach(r => Console.WriteLine(GetRow($"{r.EmpId}",$"{r.TotalInsuredAmt:C}",$"{r.RoutineCheckup}",$"{r.CheckupCharge:C}",$"{r.RemainingBalance:C}")));
GetKeyFromUser("\nDone! Press any key to exit...");
输出
,我的建议是,如果源不是IQueryable而是IEnumerable,则使用Queryable.GroupJoin的重载之一,或它的IEnumerable等效项。
使用GroupJoin,您可以获得“所有雇员,每个雇员的零个或多个例行检查”。通过使用参数resultSelector,可以创建所需的输出。
GroupJoin的优势在于,您还将获得到目前为止尚未进行过检查的员工。如果您使用Join,那么您根本不会得到这些雇员。
var employeesWithTheirCheckups = dbContext.Employees.GroupJoin(
dbContext.RoutineCheckUps,employee => employee.EmpId,// from every Employee take the primary key
checkup => checkup.EmpId,// from every RoutineCheckup take the foreign key
// to the Employee
// parameter resultSelector: for every Employee and his zero or more Checkups,// make one new object:
(employee,checkupsOfThisEmployee) => new
{
EmpId = employee.Id,TotalInsuredAmount = employee.TotalInsuredAmount,Checkups = checkupsOfThisEmployee.Select(checkup => new
{
RoutineCheckup = checkup.RoutineCheckup,CheckupCharge = checkup.CheckupCharge,// TODO: Remaining Amount
})
.ToList(),});
剩余的检查费用,等于该雇员的总金额减去此“该雇员直到这次检查的总检查费用”。
因此,对于具有RoutineCheckup 2的历史记录,您需要对具有RoutineCheckups
计算方法如下:
var chargedUntilNow = checkupsOfThisEmployee
.Where(checkupOfThisEmployee => checkupOfThisEmployee <= checkup)
.Select(checkupOfThisEmployee => checkupOfThisEmployee.CheckUpCharge)
.Sum();
剩余的是该雇员的总数-chargeUntilNow。
返回GroupJoin:
(employee,checkupsOfThisEmployee) => new
{
EmpId = employee.Id,Checkups = checkupsOfThisEmployee.Select(checkup => new
{
RoutineCheckup = checkup.RoutineCheckup,// remaining is the total of this employee - chargedUntilNow.
RemainingAmount = employee.TotalInsured -
checkupsOfThisEmployee
.Where(checkupOfThisEmployee => checkupOfThisEmployee <= checkup)
.Select(checkupOfThisEmployee => checkupOfThisEmployee.CheckUpCharge)
.Sum();
})
.ToList(),
结果是所有雇员(当然,只有他的ID和他的总保险金额)的序列,每个雇员的检查次数为零或更多。每个Checkup将具有RoutineCheckup编号,CheckupAmount和RemainingAmount。
好东西:您还将拥有尚未进行检查的员工!
此外:[EmpId,TotalInsuredAmount],每个员工只能转移一次。如果您将使用标准的Join,则每个Checkup将发送相同的[EmpId,TotalInsuredAmount]。
如果要展平,如最终结果一样,请使用SelectMany。继续使用LINQ:
.SelectMany(groupJoinResult,groupJoinResult.Checkups,// parameter resultSelector: take the GroupJoinResult,and each one of its Checkups
// to make one new:
(groupJoinResult,checkupOfThisGroupJoinResult) => new
{
EmpId = groupJoinResult.EmpId,TotalInsuredAmount = groupJoinResult.TotalInsuredAmount,RoutineCheckUp = checkupOfThisGroupJoinResult.RoutineCheckup,CheckupCharge = checkupOfThisGroupJoinResult.CheckupCharge,RemainingAmount = checkupOfThisGroupJoinResult.RemainingAmount,});
问题是您将失去尚未进行任何检查的Employee。要解决此问题,您必须提供默认值