这是我的第一篇帖子,所以如果我在一些问题上失败了,我很抱歉,但是我会尽量澄清,这样你就可以跟着我了。
我正在创建一个程序,检查合作伙伴(来自我工作的公司)是否有有效的法规(高级合作伙伴、认证合作伙伴和解决方案合作伙伴)。为了确认这一点,我检查他们的技术人员是否有有效的证书,所有的一切都运行良好的认证伙伴和解决方案合作伙伴。
因此,对于高级合伙人,我必须检查他们是否有所需的5项法规,但3人必须采取3个不同的法规。
所以每个合伙人法规都有我制定的规则,它很好,因为它只检查这5条法规。所以对于Premiun合作伙伴,我需要在规则验证之后做一些工作。
public async Task<bool> ValidateThirdPartyTypeRuleAsync(Partner partner, SpecializationExecutionThirdPartyType thirdPartyType)
{
try
{
if (!string.IsNullOrEmpty(thirdPartyType.CRPValidationRule))
{
//Check if rule is valid
using (var rule = new Evaluate(typeof(Partner), thirdPartyType.CRPValidationRule))
{
if (partner == null)
{
throw new ArgumentNullException("Partner", "Partner cannot be null for ValidateThirdTypeRule execution");
}
//Run rule with partner
var result = await rule.RunAsync(partner);
if ((bool)result == true && partner.ThirdPartyType == "PPP")
{
//Gets a list of technicians with valid satatutes for "PPP"
List<Technician> ValidTechnicianList = partner.Technicians.FindAll(s =>
s.StatutesHistory.Exists(a => (new int[] { 6, 11, 12, 8, 9 }).Contains(a.StatuteID) && a.Active)).ToList();
//Returns if partner is valid for the statute
if (ValidTechnicianList.Count() >= 3)
{
return true;
}
else
{
return false;
}
}
//Returns if partner is valid for his statute
return (bool)result;
}
}
}所以正如你可以想象的那样,这个"Count>=3“不能完成这项工作,因为如果1名技术员作为5名所需的认证,而其他2名技术人员只有一名相同的证书,那么它将返回"True”。
这是Premiun伙伴的规则:
Technicians.Where(a => a.StatutesHistory.Exists(b => new int[] {6, 11}.Contains(b.StatuteID) && b.Active == true)).Count() >= 1 &&
Technicians.Where(a => a.StatutesHistory.Exists(b => new int[] {12}.Contains(b.StatuteID) && b.Active == true)).Count() >= 1 &&
Technicians.Where(a => a.StatutesHistory.Exists(b => new int[] {8}.Contains(b.StatuteID) && b.Active == true)).Count() >= 1 &&
Technicians.Where(a => a.StatutesHistory.Exists(b => new int[] {9, 25}.Contains(b.StatuteID) && b.Active == true)).Count() >= 1 &&
Technicians.Where(a => a.StatutesHistory.Exists(b => new int[] {5, 26}.Contains(b.StatuteID) && b.Active == true)).Count() >= 1提前感谢,继续做好工作。
发布于 2018-01-03 13:02:08
好吧,首先,抱歉,我之前的回答显然是错的。这里需要的是一种从不同数量的集合中生成笛卡尔产品的方法。
埃里克·利珀特有一篇关于这个主题的精彩文章,还有一种非常优雅的解决方案,您可以在下面的文章中找到:用LINQ计算直角积。
//Eric Lippert's implementation
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this
IEnumerable<IEnumerable<T>> sequences)
{
var emptyProduct =
new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item }));
}现在,你的问题很容易解决:
var requiredDistinct = new[] { 6, 11, 12 };
var distinctStatutes =
technicians.Select(t => t.StatuteIds)
.CartesianProduct()
.Select(p => p.Distinct())
.Where(p => requiredDistinct.All(
requiredId => p.Contains(requiredId)));Distinct的重复ids。现在,我们的条件只有在以下情况下才能得到满足:
if (distincStatues.Count() >= requiredDistinct.Length)
{
//condition met
}发布于 2018-01-03 14:32:36
一个通用的解决方案(使用任意数量的约束)将是使用回溯或不同的技术创建一个实际的结果。
为每个所需的法规/证书指定一名技术人员,检查约束条件。
/// <summary>
/// recursive solution (backtracking)
/// </summary>
/// <param name="Technicians">All technicians (possibly pre-filtered so they have at least one relevant certificate)</param>
/// <param name="DistinctSlots">The resulting statute assignment. The input needs to satisfy correctnessRule(DistinctSlots)</param>
/// <param name="ProcessingSet">The statute IDs to be assigned according to the rules</param>
/// <param name="completenessRule">A predicate that checks the completeness of a result. It will be applied when a possible solution is fully assigned</param>
/// <param name="correctnessRule">A predicate that checks the correctness of an assignment. It needs to be true even for valid sub-results where some statutes are not assigned</param>
/// <returns>True if DistinctSlots contains a solution</returns>
private static bool FillSlots(List<Technician> Technicians, Dictionary<int, Technician> DistinctSlots, IEnumerable<int> ProcessingSet, Predicate<Dictionary<int, Technician>> completenessRule, Predicate<Dictionary<int, Technician>> correctnessRule)
{
if (!ProcessingSet.Any())
{
return completenessRule(DistinctSlots);
}
var key = ProcessingSet.First();
var nextSet = ProcessingSet.Skip(1);
foreach (var tech in Technicians.Where(x => x.StatutesHistory.Any(y => y.StatuteID == key)))
{
DistinctSlots[key] = tech;
if (correctnessRule(DistinctSlots) &&
FillSlots(Technicians, DistinctSlots, nextSet, completenessRule, correctnessRule))
{
return true;
}
}
DistinctSlots.Remove(key);
return false;
}一个完整的结果必须满足completenessRule,它可以实现为
private static int[] StatuteIDs = new int[] { 6, 11, 12, 8, 9 };
private static bool CompletenessRule(Dictionary<int, Technician> assignment)
{
// ensure all statuteIDs are available as keys in the dictionary and all values are not-null
return !StatuteIDs.Except(assignment.Keys).Any() &&
assignment.Values.All(x => x != null);
}正确的结果必须满足correctnessRule。此示例规则将允许技术人员拥有多个法规(9、12、.)但这将需要为第6、第8和第11条提供独特的技术人员:
private static bool CorrectnessRule(Dictionary<int, Technician> assignment)
{
return
CompareNullOrDifferent(assignment, 6, 8) &&
CompareNullOrDifferent(assignment, 6, 11) &&
CompareNullOrDifferent(assignment, 8, 11);
}
private static bool CompareNullOrDifferent(Dictionary<int, Technician> assignment, int key1, int key2)
{
Technician t1, t2;
return
!assignment.TryGetValue(key1, out t1) ||
!assignment.TryGetValue(key2, out t2) ||
t1 != t2;
}按以下方式执行解决程序:
Dictionary<int, Technician> DistinctSlots = new Dictionary<int, Technician>();
bool foundResult = false;
foundResult = FillSlots(Technicians, DistinctSlots, StatuteIDs, CompletenessRule, CorrectnessRule);
if (!foundResult)
{
Console.WriteLine("Not enough different technicians");
}
else
{
Console.WriteLine("Enough different technicians");
}有一些List<Technician> Technicians输入。
发布于 2018-01-03 16:05:07
您可以通过这个查询进行第一次检查(所有5个状态):
var hasAllRequired = !(new int[] { 6, 11, 12, 8, 9 }
.Except(partner.Technicians
.SelectMany(t => StatutesHistory.Select(h => h.StatuteID))).Any());这个查询的第二个检查是:
var pass3Check = partner.Technicians
.Select(t => t.StatutesHistory.Select(h => h.StatuteID).Distinct().Count())
.Count(statusCount => statusCount >= 3) >= 3;最后一个查询首先为每个技术人员创建一个不同状态计数的列表(直到Count())为止),然后检查其中至少3个是否有3个或更多的计数。
顺便说一句,通过为您的状态值引入一个enum,可以使您的生活更加轻松。
https://stackoverflow.com/questions/48076938
复制相似问题