哪个是在逗号分隔字符串中查找重复项的更好方法?

时间:2012-12-12 11:55:56

标签: c# linq

我有以下两种方法。方法1使用HashSet和List。第二种方法使用Sorting of Array

processing speed

而言哪个更好
  1. 当有很多记录?
  2. 当记录数量很少时?
  3. CODE

            string entryValue = "A,B, a , b, ";
    
            if (!String.IsNullOrEmpty(entryValue.Trim()))
            {
    
                //APPROACH 1
                bool isUnique = true;
    
                //Hash set is unique set  -- Case sensitivty Ignored
                HashSet<string> uniqueRecipientsSet = new HashSet<string>(entryValue.Trim().Split(',').Select(t => t.Trim()),StringComparer.OrdinalIgnoreCase );
    
                //List can hold duplicates
                List<string> completeItems = new List<string>(entryValue.Trim().Split(',').Select(t => t.Trim()));
    
                if (completeItems.Count != uniqueRecipientsSet.Count)
                {
                    isUnique = false;
                }
    
    
                //APPROACH 2
                bool isUniqueCheck2 = true;
                string[] words = entryValue.Split(',');
                Array.Sort(words);
    
                for (int i = 1; i < words.Length; i++)
                {
                    if (words[i].ToLower().Trim() == words[i - 1].ToLower().Trim())
                    {
                        isUniqueCheck2 = false;
                        break;
                    }
                }
    
    
                bool result1 = isUnique;
                bool result2 = isUniqueCheck2;
    
    
            }
    

    参考文献:

    1. Split comma separated string to count duplicates
    2. MSDN Blog - Find Duplicates using LINQ

3 个答案:

答案 0 :(得分:1)

您可以简化第一种方法:

List<string> completeItems = new List<string>(entryValue.Trim().Split(',').Select(t => t.Trim()));
isUnique = completeItems.Count == completeItems.Distinct().Count();

这将消除多次拆分,并隐藏Distinct()调用后的哈希集。请注意,if语句也是不必要的。

答案 1 :(得分:1)

哈希集方法是O(n);排序方法是O(n log n)。

然而,更快的选择是通过在第一次看到副本时立即停止来短路hashset方法:

HashSet<string> uniqueRecipientsSet
    = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
bool isUnique = true;

foreach(var item in entryValue.Split(',').Select(t => t.Trim()))
{
    if (!uniqueRecipientsSet.Add(item))
    {
        isUnique = false;
        break;
    }
}

可以隐藏LINQ中的foreach循环:

HashSet<string> uniqueRecipientsSet
    = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
bool isUnique = entryValue.Split(',').Select(t => t.Trim())
    .All(i => uniqueRecipientsSet.Add(i));

这是“LINQ-with-side-effects”但确实将整个事情减少到两行。

您可以编写自己的AreAllDistinct扩展方法,以避免副作用:

public static bool AreAllDistinct<T>(
    this IEnumerable<T> source, IEqualityComparer<T> comparer)
{
    HashSet<T> checker = new HashSet<T>(comparer);
    foreach (var t in T)
        if (!checker.Add(t))
            return false;
    return true;
}

bool isUnique = entryValue.Split(',').Select(t => t.Trim())
    .AreAllDistinct(StringComparer.OrdinalIgnoreCase);

答案 2 :(得分:1)

您可以自己使用StopWatch。第一种方法更快一点:

1) 00:00:00.0460701  2) 00:00:00.0628364

每种方法10000次重复(只是一种测量时间的简单方法)