在 C# 中更改哈希表中字符串的一个元素

本文关键字:一个 元素 字符串 哈希表 | 更新日期: 2023-09-27 18:37:14

我必须编写一个使用哈希表的程序,键/值由用户输入。在程序中,我必须输出所有键,但是如果任何键以小"a"开头,我必须让它以大"A"开头。我在最后一步有问题。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Hashtable hashtable = new Hashtable();
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("Vnesete kluc");
                string kluc = Console.ReadLine();
                Console.WriteLine("Vnesete podatok");
                string podatok = Console.ReadLine();
                hashtable.Add(kluc, podatok);
            }
            foreach (string klucevi in hashtable.Keys)
            {
                if (klucevi[0] == 'a')
                {
                    klucevi[0] = 'A';
                }
                Console.WriteLine(klucevi);
            }
        }
    }
}

我在将字符串的第一个元素转换为"a"到"A"的行上收到错误。

在 C# 中更改哈希表中字符串的一个元素

您无法动态更改密钥。最简单的方法是在添加到集合之前检查密钥:

for (int i = 0; i < 10; i++)
{
    Console.WriteLine("Vnesete kluc");
    string kluc = Console.ReadLine();
    if (kluc.StartsWith("a"))
        kluc = "A" + kluc.Substring(1);
    Console.WriteLine("Vnesete podatok");
    string podatok = Console.ReadLine();
    hashtable.Add(kluc, podatok);
}

您的问题与哈希表无关。您有一个编译错误,因为在 .NET 中字符串是不可变的。

其次,这是不相关的,不能将 foreach 循环变量分配给。

所以,而不是

foreach (string klucevi in *whatever*)
{
    if (klucevi[0] == 'a')
    {
        klucevi[0] = 'A';
    }
    Console.WriteLine(klucevi);
}

foreach (string klucevi in *whatever*)
{
    var temp = klucevi;
    if (temp[0] == 'a')
    {
        StringBuilder sb = new StringBuilder(temp);
        sb[0] = 'A';
        temp = sb.ToString();
    }
    Console.WriteLine(temp);
}

不要忘记包含using System.Text;声明。

更新:上面的 aswer 显示了在 .NET 中修改字符串的通用方法,而不仅仅是替换一个字符。

此外,有些人对这种方法的效率表示担忧。他们错了。在这篇关于未记录的字符串的练习文章中提供了更多信息。

更新 2:我喜欢接受挑战。虽然它与手头的问题完全无关,但与使用"A" + temp.Substring(1)相比,关于使用 StringBuilder 的有效性的讨论已经合并。因为我喜欢事实,我想有些读者会同意,所以我运行了一个小基准。

我在 64 位 Windows 7 机器上运行了测试,其中 .NET 4.5 作为 32 位和 64 位进程。事实证明,StringBuilder方法总是比替代方案快20%左右。内存使用量大致相同。扬子晚报.

对于那些愿意重复测试的人,以下是源代码:

using System;
using System.Diagnostics;
using System.Text;
static class Program
{
    static void Main(string[] args)
    {
        for (int length = 50; length <= 51200; length = length * 2)
        {
            string input = new string(' ', length);
            // warm up
            PerformTest(input, 1);
            // actual test
            PerformTest(input, 100000);
        }
    }
    static void PerformTest(string input, int iterations)
    {
        GC.Collect();
        GC.WaitForFullGCComplete();
        int gcRuns = GC.CollectionCount(0);
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = iterations; i > 0; i--)
        {
            StringBuilder sb = new StringBuilder(input);
            sb[0] = 'A';
            input = sb.ToString();
        }
        long ticksWithStringBuilder = sw.ElapsedTicks;
        int gcRunsWithStringBuilder = GC.CollectionCount(0) - gcRuns;
        GC.Collect();
        GC.WaitForFullGCComplete();
        gcRuns = GC.CollectionCount(0);
        sw = Stopwatch.StartNew();
        for (int i = iterations; i > 0; i--)
        {
            input = "A" + input.Substring(1);
        }
        long ticksWithConcatSubstring = sw.ElapsedTicks;
        int gcRunsWithConcatSubstring = GC.CollectionCount(0) - gcRuns;
        if (iterations > 1)
        {
            Console.WriteLine(
                "String length: {0, 5} With StringBuilder {1, 9} ticks {2, 5} GC runs, alternative {3, 9} ticks {4, 5} GC Runs, speed ratio {5:0.00}", 
                input.Length, 
                ticksWithStringBuilder, gcRunsWithStringBuilder, 
                ticksWithConcatSubstring, gcRunsWithConcatSubstring, 
                ((double)ticksWithStringBuilder) / ((double)ticksWithConcatSubstring));
        }
    }
}