优化双foreach循环

时间:2012-11-15 13:53:17

标签: c# dictionary

我有一个双foreach循环,想要通过使它成为一个循环而不是两个来加速它。

这个想法是它从字典中获取一个元素并将其与字典中的所有元素进行比较

foreach (KeyValuePair<Int64, string> kvp in originCounts)
{
    foreach (KeyValuePair<Int64, string> testkvp in originCounts)
    {
    //Run Comparison on testkvp ad kvp
    }
}

我想把它变成一个循环,有什么建议吗?

6 个答案:

答案 0 :(得分:2)

您可以使用Enumerable.All检查所有元素是否相同:

var firstID = originCounts.First().Value.UserID;
bool allEquals = originCounts.Skip(1).All(o => o.Value.UserID == firstID);

这似乎是你真正想要的。

我刚刚在duplicate question中挑选了一个类别的字段,听起来是一个合理的标识符。

public class MyObject 
{
    public string FirstName{ get; set; }
    public string LastName{ get; set; }
    public int UserID { get; set; }
    public string Address { get; set; }
}

修改:根据您的评论,您要确定对象字段中的任何是否与另一个对象的同一字段不同。

var first = originCounts.First().Value;
bool allEquals = originCounts.Skip(1).All(o =>
                o.Value.FirstName == first.FirstName
             && o.Value.LastName  == first.LastName
             && o.Value.UserID    == first.UserID
             && o.Value.Address   == first.Address);

答案 1 :(得分:0)

您可以尝试使用linq语法并比较性能

e.g。

foreach(KeyValuePair<long, string> kvp1 in originCounts.SelectMany(kvp1 => originCounts.Select(testkvp => kvp1), (kvp1, kvp) => kvp1)) {

}

foreach(KeyValuePair<long, string> kvp1 in from kvp1 in originCounts
                                                 from kvp in originCounts.Select(testkvp => kvp1)
                                                 select kvp1) {
}

答案 2 :(得分:0)

您可以创建一个可比较的字符串键值类来实现IComparable接口。

public class ComparableString : IComparable
{
    public Int64 Key { get; set; }

    public string Value { get; set; }

    public int CompareTo(object obj)
    {
        if (obj == null) return 1;

        string otherString = obj as ComparableString;

        if (otherString != null)
        {
            // PLACE YOUR COMPARE LOGIC HERE
            return this.Value.CompareTo(otherString.Value);
        }
        else
        {
            throw new ArgumentException("Object is not a Comparable String");
        }
    }
}

执行此操作后,您可以创建链接列表并运行.sort方法

var originCounts= new List<ComparableString>();
// Logic to fill your list
originCounts.Sort();

.Sort方法的平均复杂度为O(n(log n)),最坏的情况为O(n ^ 2),请参阅http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx以获取更多信息。

一旦调用.Sort()方法,您就会知道项目索引之前的任何值小于或等于项目的值,并且任何大于您所在索引的索引都是大于或等于物品的价值。

答案 3 :(得分:0)

也许我误解了这个问题,但是如果你只是想在字符串中找到重复的值,你可以使用Dictionary的Values属性,并对它们做一个区别。

使用您的词典示例:

    Dictionary<Int64, string> originalCounts = new Dictionary<Int64, string>();
    for (Int64 i = 0; i < 10; i++)
    {
        originalCounts.Add(i, i.ToString());
    }
    originalCounts[5] = originalCounts[3];

    foreach (var kvp in originalCounts)
    {
        Console.WriteLine("{0}  {1}", kvp.Key, kvp.Value);
    }

    Console.WriteLine();

    foreach (var value in originalCounts.Values.Distinct())
    {
        Console.WriteLine("{0}", value);
    }

答案 4 :(得分:0)

如果我理解正确,要获取不同的对象(不实现IComparable或覆盖Equals和GetHashcode):

var noDups = originCounts
                                 //Any Prop. you want to compare
              .GroupBy(o => new { o.FirstName, o.LastName, o.UserID, o.Address })
              .Select(g => g.First())
              .ToList();

答案 5 :(得分:-1)

为什么要将字典条目与同一字典中的其他条目进行比较?你在检查重复吗?如果是,您可以使用originCounts.Distinct()

修改:您需要为IEqualityComparer方法指定Distinct,否则它只会比较键(在Dictionary中始终不同),而不是值。