首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我有5条法规,我需要确保3条法规被3条不同的人占用。

我有5条法规,我需要确保3条法规被3条不同的人占用。
EN

Stack Overflow用户
提问于 2018-01-03 11:58:13
回答 3查看 129关注 0票数 2

这是我的第一篇帖子,所以如果我在一些问题上失败了,我很抱歉,但是我会尽量澄清,这样你就可以跟着我了。

我正在创建一个程序,检查合作伙伴(来自我工作的公司)是否有有效的法规(高级合作伙伴、认证合作伙伴和解决方案合作伙伴)。为了确认这一点,我检查他们的技术人员是否有有效的证书,所有的一切都运行良好的认证伙伴和解决方案合作伙伴。

因此,对于高级合伙人,我必须检查他们是否有所需的5项法规,但3人必须采取3个不同的法规。

所以每个合伙人法规都有我制定的规则,它很好,因为它只检查这5条法规。所以对于Premiun合作伙伴,我需要在规则验证之后做一些工作。

代码语言:javascript
复制
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伙伴的规则:

代码语言:javascript
复制
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

提前感谢,继续做好工作。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-01-03 13:02:08

好吧,首先,抱歉,我之前的回答显然是错的。这里需要的是一种从不同数量的集合中生成笛卡尔产品的方法。

埃里克·利珀特有一篇关于这个主题的精彩文章,还有一种非常优雅的解决方案,您可以在下面的文章中找到:用LINQ计算直角积

代码语言:javascript
复制
//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 }));
}

现在,你的问题很容易解决:

代码语言:javascript
复制
 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)));
  1. 我们计算所有法规ids的笛卡儿积。
  2. 我们过滤掉每个产品上调用Distinct的重复ids。
  3. 然后,我们过滤掉所有的产品,而这些产品并不是所有需要的法规。

现在,我们的条件只有在以下情况下才能得到满足:

代码语言:javascript
复制
if (distincStatues.Count() >= requiredDistinct.Length)
{ 
    //condition met
}
票数 1
EN

Stack Overflow用户

发布于 2018-01-03 14:32:36

一个通用的解决方案(使用任意数量的约束)将是使用回溯或不同的技术创建一个实际的结果。

为每个所需的法规/证书指定一名技术人员,检查约束条件。

代码语言:javascript
复制
/// <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,它可以实现为

代码语言:javascript
复制
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条提供独特的技术人员:

代码语言:javascript
复制
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;
}

按以下方式执行解决程序:

代码语言:javascript
复制
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输入。

票数 0
EN

Stack Overflow用户

发布于 2018-01-03 16:05:07

您可以通过这个查询进行第一次检查(所有5个状态):

代码语言:javascript
复制
var hasAllRequired = !(new int[] { 6, 11, 12, 8, 9 }
    .Except(partner.Technicians
        .SelectMany(t => StatutesHistory.Select(h => h.StatuteID))).Any());

这个查询的第二个检查是:

代码语言:javascript
复制
var pass3Check = partner.Technicians
    .Select(t => t.StatutesHistory.Select(h => h.StatuteID).Distinct().Count())
    .Count(statusCount => statusCount >= 3) >= 3;

最后一个查询首先为每个技术人员创建一个不同状态计数的列表(直到Count())为止),然后检查其中至少3个是否有3个或更多的计数。

顺便说一句,通过为您的状态值引入一个enum,可以使您的生活更加轻松。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48076938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档