【问题标题】:C# loop through sets of items in list [closed]C#循环遍历列表中的项目集[关闭]
【发布时间】:2015-02-02 09:24:00
【问题描述】:

我有字符串列表,有时列表中有超过 10.000.000 个字符串。

我需要遍历列表并将这些数据块发送到 API,每个 API 调用包含 2k 个字符串的子列表。

最有效的方法是什么?

【问题讨论】:

  • 你在内存中是否有完整的列表,字面意思是List<string>?你可以只使用索引吗?你试过什么了? (与此评论的先前版本相反,看起来 LINQ to Objects 确实优化 Skip,因此重复使用 Skip/Take 会很慢。不过还有其他各种与 LINQ 相关的选项.. .)

标签: c# list


【解决方案1】:

明智地将 LINQ TakeSkip 运算符用于变量。

例如语法如下-

IEnumerable<resultStrings> page1 = myStrings.Skip(0).Take(2000);            
IEnumerable<resultStrings> page2 = myStrings.Skip(2000).Take(2000);  

【讨论】:

  • 有 1000 万个字符串,这非常慢。
  • 同意。但这是在对问题进行更多详细说明之前的第一次尝试:-)
【解决方案2】:

试试 GetRange 方法:

        List<int> list = new List<int>() { 1, 2, 3, 4, 5};

        var chunk = 2;
        var iterations = list.Count / chunk;

        for (int i = 0; i < iterations; i++)
        {
            var portion = list.GetRange(chunk * i, chunk);
            //Do API
        }

        var remainder = list.GetRange(chunk * iterations, list.Count - chunk * iterations);
        //Do API

您可以查看 GetRange 与 GetRange 获胜的一些基准测试。 https://icodeit.wordpress.com/2012/08/27/performance-of-skip-and-take-in-linq-to-objects/

【讨论】:

  • 但是GetRange 需要一遍又一遍地在内存中创建新列表,而Skip/Take 只需要CPU 而不需要额外的内存。 OP 必须决定什么更重要。
  • ++ 但在大多数情况下,这应该是最有效和最直接的方法。
  • 是的,但是如果有引用类型列表,我认为内存消耗不会那么大
【解决方案3】:

可能最有效的方法是使用数据库而不是全部加载到内存中(从任何地方),然后使用Skip/Take 来获取其中的一部分。

但是,您可以使用GroupBy:

var chunks = largeStringList.Select((str, index) => new { str, index })
    .GroupBy(x => x.index / 2000, x => x.str);
foreach (var chunkGroup in chunks)
    Console.WriteLine(String.Join(",", chunkGroup));

我用这个结果进行了一些性能测试:

List.GetRange

00:00:00.0404119 (40 milliseconds)

(我的)GroupBy

00:00:02.2386504 (two seconds)

Skip/Take

00:10:11.6467726 (yes, more than 10 minutes)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 2012-02-23
    相关资源
    最近更新 更多