递归函数重复值检查 [英] recursion function to duplicate value check

查看:89
本文介绍了递归函数重复值检查的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

protected void btnSave_Click(object sender, EventArgs e)
        {

            string result = string.Empty;
            string FacilityId = string.Empty;
            int current;



            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
           // var random0 = new Random();
            result = new string(
                Enumerable.Repeat(chars, 1)
                          .Select(s => s[random.Next(s.Length)])
                          .ToArray());

            lock (syncLock)
            { // synchronize
                current = random.Next(10000, (99999));
                FacilityId = result + current;
                bool duplicate = DuplicateCheck(FacilityId);
                if (duplicate == true)
                {
                    current = random.Next(10000, (99999));
                    FacilityId = result + current;
                    bool duplicate1 = DuplicateCheck(FacilityId);
                }
            }

        }







private bool DuplicateCheck(string FacilityId)
        {
            bool Flag=false;
            var duplicate = objDB.SelectAll().Where(a => a.FacilityID == FacilityId).ToList();
            if (duplicate.Count > 0)
            {
                current = random.Next(10000, (99999));
                FacilityId = result + current;
                Flag = true;
            }
            return Flag;
        }





第一种方法是生成FacilityId,对于重复检查,我使用了另一种名为DuplicateCheck的方法。我想要使用递归方法进行重复检查,直到DuplicateCheck方法返回false。



如果有人有任何想法请分享。

谢谢。



Above 1st method is to generate FacilityId and for duplicate check i have used another method named DuplicateCheck.Here i want to use recursion method for duplicate check till DuplicateCheck Method Return false.

If anyone have any idea please share.
Thanks.

推荐答案

您不需要递归方法 - 循环可以解决这个问题:

You don't need a recursive method - a while loop will do the trick:
current = random.Next(10000, 99999);
FacilityId = result + current;

while (objDB.SelectAll().Any(a => a.FacilityID == FacilityId))
{
    current = random.Next(10000, 99999);
    FacilityId = result + current;
}


递归有其用途,但在这种情况下你不应该使用它。

这是一篇文章讨论递归与迭代解决方案:

反思递归的实用性 [ ^ ]

这是一个讨论在生产代码中使用递归的论坛帖子:

不要在生产代码中使用递归吗? [ ^ ]



在您的情况下,递归没有任何好处。相反,你冒着堆栈溢出的风险,如果random.Next(..)没有产生未使用的FacilityId,而堆栈上有空间。



备选1:既不递归也不迭代

顺序生成FacilityIds而不是随机生成:A10000,A10001,..,A99999,B10000等。

然后你就可以查询了对于使用中最高的FacilityId并计算下一个如下:

Recursion has its uses but you shouldn't use it in this case.
Here's an article discussing recursive versus iterative solutions:
Rethinking the Practicalities of Recursion[^]
And here's a forum thread discussing the use of recursion in production code:
Don't ever use recursion in production code?[^]

In your case, recursion has no benefit. Instead, you risk a stack overflow in case random.Next(..) not yielding an unused FacilityId while there's space on the stack.

Alternative 1: Neither recursion nor iteration
Generate your FacilityIds sequentially instead of randomly: A10000, A10001, .., A99999, B10000, etc.
Then you can just query for the highest FacilityId in use and calculate the next one like this:
string GetNextFacilityId()
{
  lock (syncLock)
  {
    string highestFacilityIdInUse =
        objDB.SelectAll()    // see note below
             .OrderByDescending(a => a.FacilityID)
             .Select(a => a.FacilityID)
             .Take(1)
             .SingleOrDefault();

    string nextFacilityId;
    if (highestFacilityIdInUse == null)
        nextFacilityId = "A10000";
    else
    {
        // omitted here: checking highestFacilityIdInUse for correct format
        // [A-Z][10000-99999]

        char c = highestFacilityIdInUse[0];
        int n = Int32.Parse(highestFacilityIdInUse.Substring(1));

        if (c == 'Z' && n == 99999)
            throw new InvalidOperationException("ran out of FacilityIds");
        else if (n == 99999)
            nextFacilityId = (char)(c+1) + "10000";
        else
            nextFacilityId = c + (n+1).ToString();
    }

    return nextFacilityId;
  }
}



关于SelectAll():我不知道你在这里使用哪种数据库访问技术。在此查询中,SelectAll()可能是必需的,多余的或完全错误的。请尝试使用和不使用它。 (也适用于下面的代码。)



备选2:迭代


Regarding SelectAll(): I don't know which kind of database access technology you're using here. In this query, SelectAll() might be required, superfluous or completely wrong. Please try with and without it. (Applies also to the code below.)

Alternative 2: Iteration

string GetNextFacilityId()
{
  lock (syncLock)
  {
    Random rnd = new Random();
    string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    char c = chars[rnd.Next(chars.Length)]; // simpler than your Enumerable-approach
    int n = rnd.Next(10000, 100000); // 2nd value is EXCLUSIVE upper bound!

    string nextFacilityId = c + n.ToString();
 
    while (objDB.SelectAll().Any(a => a.FacilityID == nextFacilityId))
    {
        c = chars[rnd.Next(chars.Length)];
        n = rnd.Next(10000, 100000);
        nextFacilityId = c + n.ToString();
    }

    return nextFacilityId;
  }
}





无关建议:不要使用像DuplicateCheck这样的方法名称。该名称并不意味着如果找到或找不到副本,它将会做什么。像IsDuplicate这样的名称意味着它将返回true或false。同样(或更糟糕),像Flag这样的变量名称没有说什么(Flag == false是什么意思?)。如果它被命名为isDuplicate,它会更直观。您会注意到标识符的直观名称在您几个星期没有查看代码后返回代码时会有很大帮助:)

话虽如此,我还要重命名上面的标识符c和n更有意义的东西,比如前缀和......好吧......数字左右......;)



Unrelated suggestion: Don't use a method name like "DuplicateCheck". The name doesn't imply what it will do if a duplicate is found or not found. A name like "IsDuplicate" implies that it will return true or false. Likewise (or "worse"), a variable name like "Flag" doesn't say anything (what would Flag == false mean?). It would be more intuitive if it was named "isDuplicate". You will notice that intuitive names for identifiers help a lot when you come back to your code after not looking at it for some weeks :)
Having said that, I would also rename the above identifiers "c" and "n" to something more meaningful like "prefix" and ... well.. "number" or so.. ;)


这篇关于递归函数重复值检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆