Linq - 根据 "weight" 和 "order" 从列表中获取项目
Linq - Get items from the list based on "weight" and "order"
我正在尝试创建一个 class 来计算用户配置文件的 完整性 并且我正在尝试按顺序执行后续步骤(评估程序)让用户达到下一个完整性水平。
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
列表,以便配置文件完成为 >= 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")
你可以这样做:
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
循环轻松实现...
下面的行将不起作用
.Select(evaluator => evaluator.Run(status))
您正在按照评估者进入列表<>的顺序一次枚举一个评估者。您的函数需要所有求值器才能传递整个列表 'Evaluators'.
我正在尝试创建一个 class 来计算用户配置文件的 完整性 并且我正在尝试按顺序执行后续步骤(评估程序)让用户达到下一个完整性水平。
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
列表,以便配置文件完成为 >= 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")
你可以这样做:
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
循环轻松实现...
下面的行将不起作用
.Select(evaluator => evaluator.Run(status))
您正在按照评估者进入列表<>的顺序一次枚举一个评估者。您的函数需要所有求值器才能传递整个列表 'Evaluators'.