1

我在 ASP.NET 中使用 C# 将逗号分隔的字符串列表转换为字典(通过省略任何重复项):

string str = "1,2, 4, 2, 4, item 3,item2, item 3"; //Just a random string for the sake of this example

我想知道哪种方法更有效?

1 - 使用 try/catch 块:

Dictionary<string, string> dic = new Dictionary<string, string>();

string[] strs = str.Split(',');
foreach (string s in strs)
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        try
        {
            string s2 = s.Trim();
            dic.Add(s2, s2);
        }
        catch
        {
        }
    }
}

2 - 或使用 ContainsKey() 方法:

string[] strs = str.Split(',');
foreach (string s in strs)
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        string s2 = s.Trim();
        if (!dic.ContainsKey(s2))
            dic.Add(s2, s2);
    }
}

编辑。感谢所有参与的人!

一个非常有趣的发现。如果你看下面dtb提供的答案,他提出了两种使用hashSet的方法。我会在这里给他们配音:

方法一:

var hashSet = new HashSet<string>(from s in str.Split(',')
                           where !string.IsNullOrWhiteSpace(s)
                           select s.Trim()); 

方法二:

var hashSet = new HashSet<string>();
foreach (string s in str.Split(','))
{
     if (!string.IsNullOrWhiteSpace(s))
     {
         hashSet.Add(s.Trim());
     }
}

我问他哪种方法在性能方面更快,有趣的是,方法 2 更快。这是使用 Stopwatch 类完成的计时,方法是在一个循环中运行发布版本中的每个方法 1,000,000 次:

Method 1: 1,440 ms average
Method 2: 1,124 ms average
4

5 回答 5

6

如果您需要一个集合而不是字典,我建议您使用HashSet<T> 类

HashSet<T> 类

表示一组值。

集合是不包含重复元素且其元素没有特定顺序的集合。


var hashSet = new HashSet<string>(from s in str.Split(',')
                                  where !string.IsNullOrWhiteSpace(s)
                                  select s.Trim());

或同样

var hashSet = new HashSet<string>();
foreach (string s in str.Split(','))
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        hashSet.Add(s.Trim());
    }
}
于 2012-04-08T23:14:42.873 回答
3

看起来您不需要字典:一个简单的 LINQ 表达式应该为您提供一个没有重复项的列表:

var res = str
    .Split(',')
    .Where(s => !string.IsNullOrWhitespace(s))
    .Select(s => s.Trim())
    .Distinct()
    .ToList();

如果你坚持要有字典,你可以ToDictionary改用:

var res = str
    .Split(',')
    .Where(s => !string.IsNullOrWhitespace(s))
    .Select(s => s.Trim())
    .Distinct()
    .ToDictionary(s=>s, s=>s);

强烈建议不要在正常程序流中使用try/catch,因为它隐藏了您的意图:C# 中的异常是为异常情况保留的,而不是您可以安全地用if / then / else条件捕获的常规事物。

于 2012-04-08T23:14:46.437 回答
2

方法 2 使用.ContainsKey,比抑制异常更符合语义,并且很可能更有效。

于 2012-04-08T23:14:19.453 回答
2

使用异常来控制预期的执行流程通常是不受欢迎的,而且捕获异常的成本很高,所以我会选择 v2。如果它对你来说真的很重要,为什么不建立一个基准呢?我猜 2 是“更有效率”,但你可以很容易地确认这一点。

于 2012-04-08T23:16:25.930 回答
1

如果您没有使用字典中的值,则可以使用 aHashSet<string>代替,并且将项目添加到哈希集中会自动删除重复项:

HashSet<string> set = new HashSet<string>(
  str.Split(',')
  .Select(s => s.Trim())
  .Where(s => s.Length > 0)
);
于 2012-04-08T23:22:56.910 回答