重命名带有附加增量的复制对象(即 NewObject_1)

Rename copied objects with attached increment (i.e. NewObject_1)

我目前正在开发一个使用 Treeview 控件的 WinForms 应用程序。我添加了一个复制机制来复制当前选择的 Treenode。 复制的 Treenode 对象的名称应该与原始的 Treenode 不同,方式如下: "aNode", "aNode_1", "aNode_2".

感觉Regex是要走的路。

这是我目前得到的:

string theNameToBe = "aName";
List<string> theAlreadyInUseNames   // Filled beforehand
int i = 1;
do
{
    // ToDo: Use Regex to get XXXXX_1 -> XXXXX_2 as a possible name instead of XXXXX_1_1
    Regex aPossibleNewNameRegex = new Regex( String.Format("^{0}[_]\d+$", theNameToBe),RegexOptions.IgnoreCase);

    // This does not take a previously created XXXXX_1 into account and continues to attach "_1"s to the string
    string thePossibleNewName = String.Format( theNameToBe + "_{0}", i );

    if ( !theAlreadyInUseNames.Any( s => s.Equals( thePossibleNewName, StringComparison.OrdinalIgnoreCase ) ) )
    {
        theNextAvailableName = thePossibleNewName;
        break;
    }

    i++;
} while ( i < int.MaxValue );

这只会获取后续名称,例如 "aNode"、"aNode_1"、"aNode_1_1"、...等等。

你能帮我解决我在 C# 中处理正则表达式方面缺乏专业知识的问题吗?

编辑澄清: 应确定下一个可用的空位。当稍后删除其中一个 Nodes/Names 时,就会有一个空位。因此,如果仅存在字符串 "aName"、"aName_1" 和 "aName_3",则 "aName_2" 是正确的发现。

可以像

一样简单
var selected = "node_3";
var names = new[] { "node_1", "node_3" };
var prefix = selected.Substring(0, selected.IndexOf('_') + 1);
var number = 1;
string name; // result
do
    name = prefix + number++;
while (names.Contains(name));

我可能已经找到了满足要求的解决方案。这是初稿,可能会在经过一轮单元测试和现实生活场景后进行更新。 而且总是有可能这个版本对于工作来说太复杂了,而 Sinatrs slim 方法可能就足够了。

    static void Main( string[] args )
    {
        List<string> theAlreadyInUseNames = new List<string>();

        theAlreadyInUseNames.Add( "aName" );
        theAlreadyInUseNames.Add( "aName_1" );
        theAlreadyInUseNames.Add( "aName_2" );
        theAlreadyInUseNames.Add( "aName_3" );
        theAlreadyInUseNames.Add( "aName_4" );
        theAlreadyInUseNames.Add( "aName_5" );
        theAlreadyInUseNames.Add( "aName_7" );
        theAlreadyInUseNames.Add( "aName_2_1" );
        theAlreadyInUseNames.Add( "aName_2_3" );

        string theNameToBe0 = "aName";
        string theNameToBe1 = "aName_2";
        string theNameToBe2 = "aName_2_1";

        List<string> namesToBe = new List<string>();
        namesToBe.Add( theNameToBe0 );
        namesToBe.Add( theNameToBe1 );
        namesToBe.Add( theNameToBe2 );

        string[] splits;
        char[] charSeparators = new char[] { '_' };
        string theNewNameToBe1 = string.Empty;
        string theNextAvailableName = String.Empty;

        foreach ( var item in namesToBe )
        {
            splits = item.Split( charSeparators, StringSplitOptions.RemoveEmptyEntries );


            if ( splits.Length > 1 )
            {
                int theNumber = Convert.ToInt32( splits.Last() );

                theNewNameToBe1 = splits.ElementAt( 0 );

                for ( int i = 1; i < splits.Length - 1; i++ )
                {
                    theNewNameToBe1 = theNewNameToBe1 + "_" + splits.ElementAt( i );
                }

                int counter = 1;
                string theActualNewName = string.Empty;
                do
                {

                    theActualNewName = theNewNameToBe1 + "_" + ( theNumber + counter );

                    if ( !theAlreadyInUseNames.Any( s => s.Equals( theActualNewName, StringComparison.OrdinalIgnoreCase ) ) )
                    {
                        theNextAvailableName = theActualNewName;
                        break;
                    }

                    counter++;
                } while ( counter < int.MaxValue );
            }
            else if ( splits.Length == 1 )
            {
                    int counter = 1;
                    string theActualNewName = string.Empty;

                    do
                    {
                        theActualNewName = theNameToBe + "_" + ( counter );

                        if ( !theAlreadyInUseNames.Any( s => s.Equals( theActualNewName, StringComparison.OrdinalIgnoreCase ) ) )
                        {
                            theNextAvailableName = theActualNewName;
                            break;
                        }

                        counter++;
                    } while ( counter < int.MaxValue );
            }
            else
            {
                throw new ArgumentException();
            }
        }
    }