#c# #list
#c# #Список
Вопрос:
У меня есть список транзакций на C #
public class Transaction
{
public string effectiveDate;
public string transactionType;
public double grossAmount;
public double netAmount;
}
Разные типы транзакций хранятся в разных списках, которые заполняются извлечением данных из базы данных.
В конце он выдает отчет о детализированных транзакциях.
Допустим, 15 числа месяца мне выплачивается ежемесячная плата за администрирование в размере 1,50 долл. В феврале плата отменяется, и у меня есть транзакция отмены. Итак, теперь в моем списке у меня есть
'2020-01-15', 'Admin fee', 1.5, 1.5
'2020-02-15', 'Admin fee', 1.5, 1.5
'2020-02-15', 'Admin fee', -1.5, -1.5
'2020-03-15', 'Admin fee', 1.5, 1.5
Как я могу удалить или пропустить плату за администрирование в феврале, если они равны нулю?
В других случаях у меня может быть 10 или более транзакций того же типа в тот же день, которые будут отменены, то есть 10 платежей, полученных и отмененных с той же датой вступления в силу.
Является ли сортировка по дате, повторение и сохранение общего количества значений до тех пор, пока я не перейду к новой дате, а затем сравнение с нулем самым простым / приятным способом?
Я знаю, что это было бы проще сделать в SQL с группой, имея sum <> 0, но значения хранятся в базе данных в виде символов с $ и запятой и начальным пробелом и т.д., Поэтому я не могу пойти этим путем. По разным причинам, даже если я заменяю / replace / replace / convert данные.
Спасибо
Комментарии:
1. Примечание: зачем сохранять
effectiveDate
какstring
? Поскольку это некоторая дата,DateTime effectiveDate
будет более естественным2. Добро пожаловать в StackOverflow. Пожалуйста, поделитесь с нами своими попытками узнать, как вы пытались решить проблему.
3. @DmitryBychenko Справедливый вопрос Каждый год выполняется задание ежегодного отчета, извлекающее соответствующие данные из многих таблиц и помещающее в одну таблицу транзакций. Исторически с этой таблицей не выполнялось никаких операций, поэтому они просто сохраняли все в виде строк. Затем эта таблица была прочитана и загружена в обычный текстовый файл. Вот почему в нем есть все форматирование и интервалы. Затем было написано приложение vb для создания файлов csv. Я думаю, именно тогда форматирование начало удаляться. Затем я пришел и преобразовал вывод XML в C #. Это была моя первая работа на c # несколько лет назад. Было бы много возможностей для улучшения.
Ответ №1:
Вы можете попробовать Linq для данного списка, скажем
var myList = new List<Transaction>() {
new Transaction() {
effectiveDate = "2020-01-15",
transactionType = "Admin fee",
grossAmount = 1.5,
netAmount = 1.5},
new Transaction() {
effectiveDate = "2020-02-15",
transactionType = "Admin fee",
grossAmount = 1.5,
netAmount = 1.5},
new Transaction() {
effectiveDate = "2020-02-15",
transactionType = "Admin fee",
grossAmount = -1.5,
netAmount = -1.5},
new Transaction() {
effectiveDate = "2020-03-15",
transactionType = "Admin fee",
grossAmount = 1.5,
netAmount = 1.5},
};
Вы можете поместить запрос Linq:
- Мы
GroupBy
выполняем транзакции с тем жеeffectiveDate
иtransactionType
- Проверьте, не равно ли
Sum
ofnetAmount
0 - Сгладить (
SelectMany
с последующимToList
) группы обратно в список
Код:
using System.Linq;
...
myList = myList
.GroupBy(t => new { t.effectiveDate, t.transactionType })
.Where(group => group.Sum(t => t.netAmount) != 0)
.SelectMany(group => group)
.ToList();
Комментарии:
1. Потрясающе. Возникли проблемы с запуском из-за точности double. Сумма транзакций была «не совсем» нулевой, поэтому они все еще появлялись. Исправлено с помощью
.Where(group => Math.Round(group.Sum(t => t.netAmount),2) != 0)
, но теперь появляется множество новых улучшений, которые можно внести. В настоящее время у меня есть 43 разных списка транзакций. Каждый раз, когда создается новая транзакция, я должен создавать новый список и новый код для вывода этого списка. Используя Linq, я мог бы иметь только один список и обрабатывать его совершенно по-другому. Хотя это большее изменение, которое мне может быть запрещено. Спасибо! (Я думаю) 🙂
Ответ №2:
Я думаю, вы могли бы использовать LinQ для группировки ваших результатов по дням и типу, а затем вычислить сумму сгруппированных элементов. Когда сумма ==0 пропускается…
Ответ №3:
List<Transaction> transactions;
var noUnderZeroFees = transactions.Where(x => x.netAmount > 0).ToList<Transaction>();
//noUnderZeroFees will contains Transaction items with more then Zero netAmount.
Попробуйте поискать больше о LINQ
Ответ №4:
Вы можете использовать Linq:
List<Transaction> loList = new List<Transaction>();
loList.Add(new Transaction()
{
effectiveDate = "2020-01-15",
transactionType = "Admin fee",
grossAmount = 1.5,
netAmount = 1.5
});
loList.Add(new Transaction()
{
effectiveDate = "2020-02-15",
transactionType = "Admin fee",
grossAmount = 1.5,
netAmount = 1.5
});
loList.Add(new Transaction()
{
effectiveDate = "2020-02-15",
transactionType = "Admin fee",
grossAmount = -1.5,
netAmount = -1.5
});
loList.Add(new Transaction()
{
effectiveDate = "2020-03-15",
transactionType = "Admin fee",
grossAmount = 1.5,
netAmount = 1.5
});
foreach (var loGTrans in loList.GroupBy(item => new { item.transactionType, item.effectiveDate }).Where(item => item.Sum(t => t.netAmount) != 0))
{
Console.WriteLine($"Type: {loGTrans.Key.transactionType}, Date: {loGTrans.Key.effectiveDate} -> Gross-Sum: ${loGTrans.Sum(item => item.grossAmount)} Net-Sum:${loGTrans.Sum(item => item.netAmount)}");
}
Ответ №5:
Сначала вы вводите GroupBy()
TransactionType, а затем вычисляете Sum()
значение netAmount для каждой группы. С помощью Where()
-инструкции вы включаете только те группы, которые соответствуют фильтру, а затем вы растворяете группы с помощью SelectMany()
private IEnumerable<Transaction> FilterNetZero(IEnumerable<Transaction> list)
{
return list.GroupBy(s => s.transactionType)
.Where(group => group.Sum(s => s.netAmount) != 0)
.SelectMany(group => group);
}