Reputation: 117
I have a query where I load data from a csv file
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]
};
Now when i iterate through this enumerable i want to be able to set other fields of the transaction object.
With a List I could use a for loop to loop through each one and make any changes as required, but how can you do this using a System.Linq.Enumerable?
Upvotes: 1
Views: 166
Reputation: 3626
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*/});
Without creating new object
transactions.ForEach(transaction => { transaction.AccountNo = 12; /*other manipulation*/});
Upvotes: 0
Reputation: 22073
You can convert it to a List<Transaction>
with:
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();
If you don't materialize the query, new instances of Transaction
will be created on iterating the results. The ToList()
will iterate the query and materialize the results into a list. So you can change the results.
Look here for more info: How to: Store the Results of a Query in Memory http://msdn.microsoft.com/en-us/library/bb513810.aspx
Upvotes: 1
Reputation: 172826
To be able to do this you must first 'materialize' the query to an in-memory collection, such as array:
transactions = transactions.ToArray();
foreach (var transaction in transactions)
{
// Fill other members here
}
Because if you don't do this, your changes will be lost, simply because iterating the query will create new Transaction
objects all the time.
Another option is to write a 'transformation' method that does this:
public Transaction FillOtherProperties(Transaction transaction)
{
// Fill other members here
return transaction;
}
And you can use it as follows:
transactions.Select(FillOtherProperties);
This is useful when you need the iterator to be lazy, for instance when the collection is too big to fit in memory.
Downside of this is that you're mutating existing objects which can be seen as a side effect, which can cause confusion to other developers. You would typically like your queries to be side effect free.
Upvotes: 0