1

我有一个查询,我从 csv 文件加载数据

var transactions = from line in System.IO.File.ReadAllLines(path).Skip(1)
    let columns = line.Split(',')
    select new Transaction
    {
        AccountNo = long.Parse(columns[0]),
        Date = DateTime.Parse(columns[1], new CultureInfo("en-AU")),
        DebitAmount = columns[3].Length > 0? decimal.Parse(columns[3]): 0.00m,
        CreditAmount = columns[4].Length > 0 ? decimal.Parse(columns[4]) : 0.00m,
        Categories = columns[5],
        Serial = columns[6]
    };

现在,当我遍历这个可枚举时,我希望能够设置事务对象的其他字段。

使用 List 我可以使用 for 循环遍历每个循环并根据需要进行任何更改,但是如何使用 System.Linq.Enumerable 来做到这一点?

4

3 回答 3

1

您可以将其转换为List<Transaction>

var transactions = (from line in System.IO.File.ReadAllLines(path).Skip(1)
    let columns = line.Split(',')
    select new Transaction
    {
        AccountNo = long.Parse(columns[0]),
        Date = DateTime.Parse(columns[1], new CultureInfo("en-AU")),
        DebitAmount = columns[3].Length > 0? decimal.Parse(columns[3]): 0.00m,
        CreditAmount = columns[4].Length > 0 ? decimal.Parse(columns[4]) : 0.00m,
        Categories = columns[5],
        Serial = columns[6]
    }).ToList();

如果您不具体查询,Transaction则将在迭代结果时创建新的实例。将ToList()迭代查询并将结果具体化为列表。所以你可以改变结果。

在此处查看更多信息:如何:将查询结果存储在内存中 http://msdn.microsoft.com/en-us/library/bb513810.aspx

于 2013-09-30T12:46:51.873 回答
0

为了能够做到这一点,您必须首先将查询“物化”到内存中的集合,例如数组:

transactions = transactions.ToArray();

foreach (var transaction in transactions)
{
    // Fill other members here
}

因为如果您不这样做,您的更改将会丢失,因为迭代查询会Transaction一直创建新对象。

另一种选择是编写执行此操作的“转换”方法:

public Transaction FillOtherProperties(Transaction transaction)
{
    // Fill other members here

    return transaction;
}

您可以按如下方式使用它:

transactions.Select(FillOtherProperties);

当您需要迭代器惰性时,这很有用,例如当集合太大而无法放入内存时。

这样做的缺点是您正在改变现有的对象,这可能被视为副作用,这可能会给其他开发人员造成混淆。您通常希望您的查询没有副作用。

于 2013-09-30T12:47:01.683 回答
0
        var transactions =
            System.IO.File.ReadAllLines("").Skip(1).Select(line => new { line, columns = line.Split(',') }).Select(
                strings => new Transaction
                          {
                              AccountNo = long.Parse(strings.columns[0]),
                              Date = DateTime.Parse(strings.columns[1], new CultureInfo("en-AU")),
                              DebitAmount = strings.columns[3].Length > 0 ? decimal.Parse(strings.columns[3]) : 0.00m,
                              CreditAmount = strings.columns[4].Length > 0 ? decimal.Parse(strings.columns[4]) : 0.00m,
                              Categories = strings.columns[5],
                              Serial = strings.columns[6]
                          }).ToList();

        IEnumerable<Transaction> newTransactions = transactions.Select(tr => new Transaction(){/*assign new values*/});

不创建新对象

    transactions.ForEach(transaction => { transaction.AccountNo = 12; /*other manipulation*/});
于 2013-09-30T12:47:54.953 回答