在列表中比较项目

时间:2014-10-02 14:35:20

标签: c# asp.net list loops

我有一个List<DiscountRule>,我需要迭代这些检查以查看是否有任何规则相互冲突。该规则有一些属性,例如BrandIDCategoryID,用于指示规则适用的品牌和类别以及Include/Exclude标记。

如果出现以下示例条件,则如果类别和品牌都与现有规则匹配,则规则会发生冲突:

规则1

包含品牌包含类别

规则2

排除品牌排除类别

如果规则包括排除和排除包含,反之亦然,我也会检查是否会发生冲突。

我需要一种循环遍历这些并标记列表中发生冲突的方法。这是我现在拥有的:

public bool CheckDiscountRuleClash(DiscountRule other)
{
    if (this.CategoryId == other.CategoryId && this.BrandId == other.BrandId)
    {
        if (this.BrandInclude && this.CategoryInclude
         && !other.BrandInclude && !other.CategoryInclude)
        {
            this.RuleClashes = true;
            return true;
        }
        else if (!this.BrandInclude && !this.CategoryInclude
            && other.BrandInclude && other.CategoryInclude)
        {
            this.RuleClashes = true;
            return true;
        }
        else if (this.BrandInclude && !this.CategoryInclude
            && !other.BrandInclude && other.CategoryInclude)
        {
            this.RuleClashes = true;
            return true;
        }
        else if (!this.BrandInclude && this.CategoryInclude
                && other.BrandInclude && !other.CategoryInclude)
        {
            this.RuleClashes = true;
            return true;
        }
        else
        {
            this.RuleClashes = false;
            return false;
        }
    }

    return false;
}

我称之为:

rules.Where(i1 => rules.Any(i2 => i1.CheckDiscountRuleClash(i2))).ToList();

但这显然只能让我回到那些满足Any()条件的人。有办法做我想做的事吗?

3 个答案:

答案 0 :(得分:0)

要找回符合条件的所有对,只需将每个序列投影到匹配项中:

var conflictingRules = rules.SelectMany(rule => 
    rules.Where(other => rule.CheckDiscountRuleClash(other))
    .Select(other=> new { rule, other }));

答案 1 :(得分:0)

如何使用foreach循环来确保浏览列表中的每个项目

foreach (var rule in rules) // where rules is your List<DiscountRule>
            {
                var result = CheckDiscountRuleClash(rule);
                // do something with the result here (boolean)
                ...
            }

答案 2 :(得分:-1)

您可以使用Linq join以线性时间执行此操作:

var conflictingRules =
            from rule in rules
            join other in rules
            on new{rule.BrandId, rule.CategoryId, rule.BrandInclude, rule.CategoryInclude} equals new{other.BrandId, other.CategoryId, BrandInclude = !other.BrandInclude, CategoryInclude = !other.CategoryInclude}
            select new{rule, other};

我们的想法是将列表与“对应方”一起加入 - 已知的那些与另一方相冲突。 如果需要,同样的方法还允许您将算法与SQL数据库一起使用。

请注意,此算法在线性时间内工作,优于迭代所有对(例如,使用SelectMany,即O(N ^ 2)),其他答案通过数量级,从列表几个品牌的doesens类别。

另请注意,此代码不使用原始的CheckDiscountRuleClash代码,因此它的代码小30行代码 。 您可以在此处查看实时代码并进行性能比较: https://dotnetfiddle.net/ZtRfcz

请注意,如果稍微增加数字,那么慢速方法会在dotnetfiddle上以5秒的时间执行超时。计算复杂性严重!