向重复字符串添加增量数字

本文关键字:数字 添加 字符串 | 更新日期: 2023-09-27 17:54:44

我在c#工作。Net4使用Visual Studio),我正试图找出一种算法,根据程序中的现有字符串,将增量数字附加到输入的字符串。不太好到处找答案

有一个List<string>。例如

{"MyItem (2)", "MyItem", "Other thing", "string here", "MyItem (1)"}

假设用户想要添加另一个字符串到这个列表中,并且他们已经选择了"MyItem"作为要添加的字符串。因此给定输入和现有列表,算法将返回"MyItem(3)"作为要添加的新字符串。

它的功能与Windows资源管理器中相同,您可以不断添加新文件夹("新文件夹(1)","新文件夹(2)"等等)

我正在尝试通过列表循环并找出下一个逻辑数字应该是什么,但我被卡住了(代码越来越大)。有人知道一种优雅的方法吗?(我不太擅长Regex,所以也许这就是我错过的)

向重复字符串添加增量数字

应该可以:

var list = new List<string>{"MyItem (2)", "MyItem", "Other thing", "string here", "MyItem (1)"}   ; 
string str = "MyItem";
string newStr = str;
int i = 0;
while(list.Contains(newStr))
{
   i++;
   newStr = string.Format("{0} ({1})",str,i);
}
// newStr = "MyItem (3)"

获取input并搜索它,如果它存在于列表中,则获取计数并连接输入字符串和count + 1,否则只需将输入添加到列表中:

var input = Console.ReadLine(); // just for example
if(list.Any(x => x == input))
{
    var count = list.Count(x => x == input);
    list.Add(string.Format("{0} ({1})", input, count+1);
} 
else list.Add(input);

下面是我用来模拟Windows资源管理器行为的一个有用的扩展方法。

我觉得前面的答案太简单,只满足了部分需求,它们也没有以一种您可以轻松重用的方式呈现。

此解决方案基于您首先确定要比较的字符串列表,它们可能来自文件系统或数据库,由您来解析来自业务域的值列表,然后识别重复项并生成唯一值的过程是非常可重复的。

扩展方法:

/// <summary>
/// Generate a uniquely numbered string to insert into this list
/// Uses convention of appending the value with the duplication index number in brackets "~ (#)"
/// </summary>
/// <remarks>This will not actually add this list</remarks>
/// <param name="input">The string to evaluate against this collection</param>
/// <param name="comparer">[Optional] One of the enumeration values that specifies how the strings will be compared, will default to OrdinalIgnoreCase </param>
/// <returns>A numbered variant of the input string that would be unique in the list of current values</returns>
public static string GetUniqueString(this IList<string> currentValues, string input, StringComparison comparison = StringComparison.OrdinalIgnoreCase)
{
    // This matches the pattern we are using, i.e. "A String Value (#)"
    var regex = new System.Text.RegularExpressions.Regex(@"'(([0-9]+)')$");
    // this is the comparison value that we want to increment
    string prefix = input.Trim();
    string result = input.Trim();
    // let it through if there is no current match
    if (currentValues.Any(x => x.Equals(input, comparison)))
    {
        // Identify if the input value has already been incremented (makes this more reusable)
        var inputMatch = regex.Match(input);
        if (inputMatch.Success)
        {
            // this is the matched value
            var number = inputMatch.Groups[1].Captures[0].Value;
            // remove the numbering from the alias to create the prefix
            prefix = input.Replace(String.Format("({0})", number), "").Trim();
        }
        // Now evaluate all the existing items that have the same prefix
        // NOTE: you can do this as one line in Linq, this is a bit easier to read
        // I'm trimming the list for consistency
        var potentialDuplicates = currentValues.Select(x => x.Trim()).Where(x => x.StartsWith(prefix, comparison));
        int count = 0;
        int maxIndex = 0;
        foreach (string item in potentialDuplicates)
        {
            // Get the index from the current item
            var indexMatch = regex.Match(item);
            if (indexMatch.Success)
            {
                var index = int.Parse(indexMatch.Groups[1].Captures[0].Value);
                var test = item.Replace(String.Format("({0})", index), "").Trim();
                if (test.Equals(prefix, comparison))
                {
                    count++;
                    maxIndex = Math.Max(maxIndex, index);
                }
            }
        }
        int nextIndex = Math.Max(maxIndex, count) + 1;
        result = string.Format("{0} ({1})", prefix, nextIndex);
    }
    return result;
}

实现:

var list = new string [] { "MyItem (2)", "MyItem", "Other thing", "string here", "MyItem (1)" };
string input = Console.ReadLine(); // simplify testing, thanks @selman-genç
var result = list.GetUniqueString(input, StringComparison.OrdinalIgnoreCase);
// Display the result, you can add it to the list or whatever you need to do
Console.WriteLine(result);
<>之前输入|结果---------------------------------MyItem | MyItem (3)Myitem (1) | Myitem (3)MyItem (3) | MyItem (3)MyItem (4) | MyItem (4)MyItem 4 | MyItem 4String Here | String Here (1)新值|新值

伪代码:如果列表中没有这样的字符串,将其添加到列表中。否则,设置变量N = 1。扫描列表并查找像给定字符串+ "(*)"这样的字符串(这里Regex会有所帮助)。如果找到任何字符串,则从大括号中取出数字并将其与N进行比较。Set N = MAX(该数字+ 1,N)。扫描列表后,N包含要添加的数字。因此,将字符串+ " (N)"添加到列表中