【问题标题】:Linq - Get items from the list based on "weight" and "order"Linq - 根据“重量”和“订单”从列表中获取项目
【发布时间】:2023-04-03 15:48:01
【问题描述】:

我正在尝试创建一个类来计算用户个人资料的完整性,并且我正在尝试获取后续步骤(评估者),以便用户实现下一个完整性级别。

public class Evaluator
{
    public Evaluator(string name, int value, Func<CompletionStatus, bool> rule)
    {
        Name = name;
        Value = value;
        Action = rule;
    }

    public int Value { get; private set; }
    public Func<Completion, bool> Rule { get; private set; }
    public bool IsCompleted { get;set; }

    public int Run(CompletionStatus status)
    {
         IsCompleted = Rule(status);
         return IsCompleted ? Value : 0;        
    }
}

class CompletionManager
{
     public List<Evaluator> Evaluators { get;set; }

     public CompletionManager() {

        Evaluators = new List<Evaluator>() {
        new Evaluator("Email", 10, status => !String.IsNullOrWhiteSpace(status.Email)),
        new Evaluator("DOB", 10, status => status.DateOfBirth.HasValue),
        new Evaluator("Mobile", 20, status => !String.IsNullOrWhiteSpace(status.Mobile)),
        new Evaluator("Address", 20, status => !String.IsNullOrWhiteSpace( status.Address)),
        new Evaluator("Profession", 40, status => status.HasProfession),

    };
}

用法

  Main() {

   var status = new CompletionStatus
            {
                Email = "dummy@gmail.com",
                DateOfBirth = null,
                Mobile = "",
                Address = "",
                HasProfession = false,
            };

    CompletionManager cm = new CompletionManager();

     var profileCompletion = (byte) cm.Evaluators
            .Select(evaluator => evaluator.Run(status))
            .Sum();

     profileCompletion.Dump(); // result= 10% complete

     var nextEvaluators = cm.EvaluatorsToTheNextLevel(profileCompletion); // get the next 40%

 }

问题:在此示例中 - 我如何获取与用户必须完成的下一个 40% 相对应的 Evaluator 列表,以便配置文件完成为 &gt;= 50%

在上面的例子中,我想得到Evaluator("DOB")Evaluator("Mobile")Evaluator("Address")

class CompletionManager {
....
 public List<Evaluator> EvaluatorsToTheNextLevel(int completionStatus) {

    // assuming completionStatus = 10%, then we have to get the next 40% worth of evaluators
       var percentBeforeNxtLevel = 50 - completionStatus;
       return Evaluators.Where(e => e.IsCompleted == false && ???);
   }
}

注意:评估者的顺序也被考虑在内,所以如果我们得到下一个 40%,我们不想要 Evaluator("Profession"),因为它在堆栈的底部

另外:这应该是灵活的;如果我这样做了

var status = new CompletionStatus
            {
                Email = "",
                DateOfBirth = null,
                Mobile = "091920",
                Address = "",
                HasProfession = false,
            };

那么我们应该得到Evaluator("Email"), Evaluator("DOB"), Evaluator("Address")

【问题讨论】:

    标签: c# linq linq-to-sql lambda


    【解决方案1】:

    你可以这样做:

    public List<Evaluator> EvaluatorsToTheNextLevel(int completionStatus) {
    
        // assuming completionStatus = 10%, then we have to get the next 40% worth of evaluators
           var percentBeforeNxtLevel = 50 - completionStatus;
           var tmp = 0;
           return Evaluators
              .Where(e => e.IsCompleted == false)
              .TakeWhile(x => {
                  tmp +=x.Value;
                  return tmp <= percentBeforeNxtLevel;
                })
               .ToList();
       }
    

    当然,这也可以通过简单的while 循环轻松实现...

    【讨论】:

      【解决方案2】:

      下面这行不行

      .Select(evaluator => evaluator.Run(status))
      ​

      您正在按照它们进入列表的顺序逐个枚举评估器。您的函数需要所有评估者,而您需要传递整个列表“评估者”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-10
        • 2019-02-24
        相关资源
        最近更新 更多