通过花很长时间的linq命令

时间:2015-07-10 10:22:10

标签: c# linq sorting csv

我有点卡住了,因为我无法理解这一点。

所以我有一个名为CSVItem的课程:

public class CSVItem
{
    public int SortedAccountNumber { get; set; }
    public DateTime Date { get; set; }
    public int SNO { get; set; }
    public string AccountNumber { get; set; }
    public double Value { get; set; }
    public int Year
    {
        get
        {
            if (Date.Month > MainWindow.fiscalMonth)
            {
                return Date.Year+1;
            }
            return Date.Year;
        }
    }
    public int StaticCounter { get { return 1; } }

    public CSVItem(string accNo, DateTime date, double value, int sNo)
    {
        Value = value;            
        Date = date;
        AccountNumber = accNo;
        SNO = sNo;
    }


}

我读了一个CSV,然后我制作了一个包含大约500k项目的CSV类型列表。然后我尝试使用列表的默认Order By方法进行排序,并尝试从已排序的集合中返回列表。这是代码:

List<CSVItem> items = new List<CSVItem>();

 // ---- some code to read csv and load into items collection

 List<CSVItem> vItems = items.OrderBy(r1 => r1.AccountNumber).ThenBy(r1 => r1.Date).ToList();

就像永远地排序然后将集合转换回列表一样。好吧,我之前已经尝试过装载大约一百万条记录,而且从来没有这样的 - 没有响应 - 来自Linq Sorting,这有点让我疯狂。关于我可以找到问题的任何帮助或建议?

1 个答案:

答案 0 :(得分:2)

您可以使用AsParallel()

List<CSVItem> vItems = items.AsParallel().OrderBy(r1 => r1.AccountNumber).ThenBy(r1 => r1.Date).ToList();

问题出现了,如果OrderBy()的并行化确实存在副作用,如果它后跟ThenBy()

AsParallel()何时拆分IEnumerable?有2个可能的答案。让我们来看看给定的查询:

items.AsParallel().OrderBy(x=>x.Age).ThenBy(x=>x.Size)

选项1

项目被拆分,每个部分按年龄排序,然后按大小排序,最后合并回1个列表。显然不是我们想要的。

选项2

项目被拆分,每个部分按年龄排序,项目合并回1个列表。之后,项目再次拆分,按大小排序并合并回1个列表。这就是我们想要的。

我创建了一个小例子来检查,哪一个是真的。

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    static void Main(string[] args)
    {
        List<TestItem> items = new List<TestItem>();
        List<TestItem> itemsNonParallel = new List<TestItem>();

        items.Add(new TestItem() { Age = 1, Size = 12 });
        items.Add(new TestItem() { Age = 2, Size = 1 });
        items.Add(new TestItem() { Age = 5, Size = 155 });
        items.Add(new TestItem() { Age = 23, Size = 42 });
        items.Add(new TestItem() { Age = 7, Size = 32 });
        items.Add(new TestItem() { Age = 9, Size = 22 });
        items.Add(new TestItem() { Age = 34, Size = 11 });
        items.Add(new TestItem() { Age = 56, Size = 142 });
        items.Add(new TestItem() { Age = 300, Size = 13 });

        itemsNonParallel.Add(new TestItem() { Age = 1, Size = 12 });
        itemsNonParallel.Add(new TestItem() { Age = 2, Size = 1 });
        itemsNonParallel.Add(new TestItem() { Age = 5, Size = 155 });
        itemsNonParallel.Add(new TestItem() { Age = 23, Size = 42 });
        itemsNonParallel.Add(new TestItem() { Age = 7, Size = 32 });
        itemsNonParallel.Add(new TestItem() { Age = 9, Size = 22 });
        itemsNonParallel.Add(new TestItem() { Age = 34, Size = 11 });
        itemsNonParallel.Add(new TestItem() { Age = 56, Size = 142 });
        itemsNonParallel.Add(new TestItem() { Age = 300, Size = 13 });

        foreach (var item in items.AsParallel().OrderBy(x => x.Age).ThenBy(x => x.Size))
        {
            Console.WriteLine($"Age: {item.Age}     Size: {item.Size}");
        }

        Console.WriteLine("---------------------------");

        foreach (var item in itemsNonParallel.OrderBy(x => x.Age).ThenBy(x => x.Size))
        {
            Console.WriteLine($"Age: {item.Age}     Size: {item.Size}");
        }

        Console.ReadLine();        
    }
}

public class TestItem
{
    public int Age { get; set; }
    public int Size { get; set; }
}

<强>结果

AsParallel()做我们想要的。它首先处理OrderBy()并行,合并回列表,然后转到下一个查询,在我们的例子中ThenBy()。我多次测试这个并且总是一样的结果。