Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 遍历IEnumerable<;字符串>;导致严重的性能问题_C#_Performance - Fatal编程技术网

C# 遍历IEnumerable<;字符串>;导致严重的性能问题

C# 遍历IEnumerable<;字符串>;导致严重的性能问题,c#,performance,C#,Performance,当我尝试遍历IEnumerable类型时,我对for循环的性能所发生的事情知之甚少 以下是导致严重性能问题的代码 foreach (IEdge ed in edcol) { IEnumerable<string> row = from r in dtRow.AsEnumerable() where (((r.Field<string>("F1") == ed.Vertex1.Name) &&

当我尝试遍历IEnumerable类型时,我对for循环的性能所发生的事情知之甚少

以下是导致严重性能问题的代码

foreach (IEdge ed in edcol)
{
    IEnumerable<string> row = 
        from r in dtRow.AsEnumerable()
        where (((r.Field<string>("F1") == ed.Vertex1.Name) && 
                (r.Field<string>("F2") == ed.Vertex2.Name))
            || ((r.Field<string>("F1") == ed.Vertex2.Name) &&
                (r.Field<string>("F2") == ed.Vertex1.Name)))
        select r.Field<string>("EdgeId");
    int co = row.Count();
    //foreach (string s in row)
    //{

    //}
    x++;
}
从代码中

row.Count()在所有循环中的最大值为10

如果我取消注释

//foreach (string s in row)
//{

//}
完成代码的执行大约需要10分钟

IEnumerable类型是否存在如此严重的性能问题

目前您有O(N*M)性能,如果N和M都很大,这可能是个问题。我倾向于预先计算一些
DataTable
info。例如,我们可以尝试:

var lookup = dtRows.AsEnumerable().ToLookup(
        row => string.Compare(row.Field<string>("F1"),row.Field<string>("F2"))<0
           ? Tuple.Create(row.Field<string>("F1"), row.Field<string>("F2"))
           : Tuple.Create(row.Field<string>("F2"), row.Field<string>("F1")),
        row => row.Field<string>("EdgeId"));
var lookup=dtRows.AsEnumerable().ToLookup(
row=>string.Compare(row.Field(“F1”)、row.Field(“F2”))和row.Field(“EdgeId”);
然后我们可以迭代:

foreach(IEdge ed in edCol)
{
    var name1 = string.Compare(ed.Vertex1.Name,ed.Vertex2.Name) < 0
           ? ed.Vertex1.Name : ed.Vertex2.Name;
    var name2 = string.Compare(ed.Vertex1.Name,ed.Vertex2.Name) < 0
           ? ed.Vertex2.Name : ed.Vertex1.Name;

    var matches = lookup[Tuple.Create(name1,name2)];
    // ...
}
foreach(在edCol中编辑边缘)
{
var name1=string.Compare(ed.Vertex1.Name,ed.Vertex2.Name)<0
?ed.Vertex1.Name:ed.Vertex2.Name;
var name2=string.Compare(ed.Vertex1.Name,ed.Vertex2.Name)<0
?ed.Vertex2.Name:ed.Vertex1.Name;
var matches=lookup[Tuple.Create(name1,name2)];
// ...
}

(注意,为了方便起见,我在这里强制使用了按字母顺序升序的配对)

这个答案是针对一个隐含的问题:“我如何使它更快”?如果这不是你想要的,我道歉,但是

您可以按名称对行进行一次分组。(我没有像Marc那样进行排序-我只是在查询时查找了两次:)


如果没有
计数
将不会对查询进行评估。性能问题可能是
dtRow.AsEnumerable()
@mipe34不太可能;这实际上没什么作用;LINQ中的大多数东西都使用延迟执行如果dtRow.AsEnumerable()是性能问题,那么为什么从代码中删除row.count()行时代码会在几秒钟内运行?@Jon那里没有与数据库对话的代码。从显示的代码中,
dtRow
看起来是一个
DataTable
DataTable
不会因为您查看它而加载自身:要么它有数据,要么它没有数据。有时我担心我们处理事情的方式有多相似。非常小的区别-为了避免
Concat
,我强制使用升序元组并使用元素投影。@marcGravel:是的。。。我不知道哪一个会更快,但我怀疑这会有多大区别。这将在3秒钟内执行datatable中约500000条记录的代码!!!谢谢lot@RajeevKumar:你明白为什么吗?@RajeevKumar:你明白为什么原始代码很慢。。。为什么如果你调用
Count()
调用(以及内部
foreach
循环),它会很快呢?@JonSkeet-er,是的,可能吧
foreach(IEdge ed in edCol)
{
    var name1 = string.Compare(ed.Vertex1.Name,ed.Vertex2.Name) < 0
           ? ed.Vertex1.Name : ed.Vertex2.Name;
    var name2 = string.Compare(ed.Vertex1.Name,ed.Vertex2.Name) < 0
           ? ed.Vertex2.Name : ed.Vertex1.Name;

    var matches = lookup[Tuple.Create(name1,name2)];
    // ...
}
var lookup = dtRow.AsEnumerable()
                  .ToLookup(r => new { F1 = r.Field<string>("F1"),
                                       F2 = r.Field<string>("F2") });
foreach (IEdge ed in edcol)
{
    // Need to check both ways round...
    var first = new { F1 = ed.Vertex1.Name, F2 = ed.Vertex2.Name };
    var second = new { F1 = ed.Vertex2.Name, F2 = ed.Vertex1.Name };
    var firstResult = lookup[first];
    var secondResult = lookup[second];

    // Due to the way Lookup works, this is quick - much quicker than
    // calling query.Count()
    var count = firstResult.Count() + secondResult.Count();

    var query = firstResult.Concat(secondResult);

    foreach (var row in query)
    {
        ...
    }
}