У меня есть 2 списка с этой структурой:

public class DepositAssembly
{
    public string VoucherNo { get; set; }
    public string Total { get; set; }
}

public class MpesaAssembly
{
    public string ReceiptNo { get; set; }
    public double PaidIn { get; set; }
}

Сбор депозитов вводится в систему ERP. Mpesa создается из файла .csv, чтобы обеспечить выполнение платежей.

Я хочу сравнить 2 списка, чтобы убедиться, что: 1. Все ваучеры / квитанции в DepositAssembly находятся в MpesaAssembly. Если нет, покажите ошибку. 2. Что у ваучеров, которые соответствуют, есть та же самая точная сумма, если суммы отличаются, показывают ошибку.

E.g. DepositAssembly   VoucherNo         Total
                       icdiihiasi        GBP 5,319.39
                       uhuixjisdjodvo    GBP 4,790.73       
     MpesaAssembly     ReceiptNo         PaidIn           
                       icdiihiasi        5,319.39
                       uhuixjisdjodvo    4,790.73

Выше должно пройти

 DepositAssembly   VoucherNo         Total
                   icdiihiasii       GBP 5,319.39
                   uhuixjisdjodvo    GBP 4,790.73       
 MpesaAssembly     ReceiptNo         PaidIn                             
                   icdiihiasi        5,319.39
                   uhuixjisdjodvo    4,790.73

Выше должен быть сбой на 1-й номер ваучера, поскольку он не может быть найден в Mpesa .csv

 DepositAssembly   VoucherNo         Total
                   icdiihiasi       GBP 5,319.39
                   uhuixjisdjodvo    GBP 4,790.73       
 MpesaAssembly     ReceiptNo         PaidIn                             
                   icdiihiasi        5,319.39
                   uhuixjisdjodvo    4,800.73

Выше должен сбой на uhuixjisdjodvo чек номер PaidIn, так как он не совпадает с номером в DepositAssembly.

Любая функция linq, чтобы сделать это?

У меня есть

   var requestWithMatches = from req in depositAssembly
                                             join resp in mpesaAssembly
                                             on req.VoucherNo equals resp.ReceiptNo  
                                             select new CallPair(req, resp);

Но это не заботиться о суммах. Необходимо сопоставить как ваучеры, так и суммы.

Как мне проверить, что номер ваучера и итоги существуют точно так же, как в сборке Mpesa? Пример Linq?

0
Kinyanjui Kamau 19 Авг 2019 в 14:57

2 ответа

Лучший ответ

Предполагая наличие следующих коллекций:

  • Deposits: сбор депозитов
  • Receipts: записи из вашего .csv файла
  • DepositsxReceipts: результат объединения Deposits и Receipts в Deposit.VoucherNo и Receipt.ReceiptNo и выбора соединенных пар (deposit, receipt)

Я опишу, как вы можете архивировать ваши цели:

  1. Все ваучеры / квитанции в DepositAssembly находятся в MpesaAssembly. Если нет, покажите ошибку.

Убедитесь, что DepositsxReceipts.Length равен Deposits.Length. На самом деле, здесь мало что происходит. В зависимости от того, сколько информации вы хотите иметь о несоответствующих парах, вам нужно будет использовать форму внешнего соединения.

  1. То, что соответствующие ваучеры имеют одинаковую точную сумму, если суммы разные, показывают ошибку.

Убедитесь, что для каждой пары (deposit, receipt) в DepositsxReceipts выполнено условие deposit.Amount == receipt.Total.

Ваша вторая цель оставляет простор для пары идей

Учитывая простое LINQ to objects , вы можете сделать следующее:

var depositsxReceipts = from deposit in deposits
                         join receipt in receipts
                         on deposit.VoucherNo equals receipt.ReceiptNo
                         select new CallPair(deposit, receipt);

В этом случае ваш CallPair класс может вычислить и выставить условие равенства суммы следующим образом:

Convert.ToDouble(deposit.Total.Split(" ").Last()) == receipt.PaidIn;

Гораздо более понятным подходом было бы изменить класс, используемый для отображения ваших записей ERP:

public class DepositAssembly
{
    public string VoucherNo { get; set; }
    // In DDD the following props would be encapsulated into a "Money" value-object
    public string Currency {get;set;} // The type of currency, eg.: GBP
    public double Total { get; set; } // The amount of the deposit
}

Тогда вычисление суммы равенства будет проще:

deposit.Amount == receipt.PaidIn;

Поскольку это довольно тривиально, вы можете выбрать между добавлением этого в свой класс CallPair или его вычислением при итерации объединенных значений (что необходимо сделать для проверки вашей второй цели).

1
Jota.Toledo 19 Авг 2019 в 15:19

По сути, это просто цикл внутри цикла, но с использованием linq-запроса «All», который сравнивает каждую DepositAssembly с каждой MpesaAssembly.

var result1 = DepositAssemblies.All(Deposit => MpesaAssemblies.Any(mpesa => mpesa.PaidIn.ToString() == Deposit.Total.ToString() &&
                                                                      mpesa.ReceiptNo.ToString() == Deposit.VoucherNo.ToString())); 

Думайте Правильный способ сделать это, хотя это создавать анонимные типы

var MatchesSolution1 = from Deposits in DepositAssemblies
                       join Mpesas in MpesaAssemblies on new { Amount = Mpesas.PaidIn.ToString(), No = Mpesas.ReceiptNo.ToString() } 
                                                  equals new { Amount = Deposits.Total.ToString(), No = Deposits.VoucherNo.ToString() }

Другое решение использует пересечение (которое должно работать быстрее всего)

var MatchesSolution2= DepositAssemblies.Select(Deposit => new { Amount = Deposit.Total.ToString(), No = Deposit.VoucherNo.ToString() })
                               .Intersect(MpesaAssemblies.Select(Mpesa => new { Amount = Mpesa.PaidIn.ToString(), No = Mpesa.ReceiptNo.ToString() }))
                               .ToList();

Надеюсь, это поможет.

1
Neil 20 Авг 2019 в 06:28