1

I have a for loop that loops a list of transactions, which all contains amount. If the amount is correct, I want that transaction to be included in a new list.

So in code:

 decimal searchAmount = 33.03;

foreach (var order in listOforders)

{ 

  if(order.amount == searchAmount)

    {
      addOrderToList()
    }

} 

The currency used doesn't use more than two decimals, so that's okay. These three scenarios, should all add the order to the list.

order.Amount = 33.03
search.Amount = 33   

order.Amount = 33.03
search.Amount = 33.03

order.Amount = 33.99
search.Amount = 33.9    

Note:

This is a search. When the customer comes back, and says "I have a problem with the product I purchased, and it's not purchased on a registered customer", searching for the amount on the customers bank receipt is a great function. This is a retail brick and mortar store scenario, so some customers choose to not register themselves.

miniHessel
  • 778
  • 4
  • 15
  • 39
  • Put the condition like if(order.amount>33 && order.amount<=33.03) – imsome1 Oct 11 '17 at 11:11
  • 3
    Can you try to elaborate on your definition of *correct*? You've just given two specific examples, can you instead try to describe what you're trying to achieve? – decPL Oct 11 '17 at 11:12
  • and what is your threshold, 33.53 should not be included? – Amit Kumar Singh Oct 11 '17 at 11:12
  • I felt it was kinda hard to elaborate a lot, but just picture an employee who wish to search for receipts to match amount. The employee can in some cases be lazy and write just 33, in other cases 33.53. Best case would perhaps be to just search without decimals? I basically want to write the matching as good as possible. – miniHessel Oct 11 '17 at 11:17
  • If you are saying values like `33`, `33.03`,`33.09`... etc are need to be considered, then you can convert your value to it's `floor value`, and then you can test your conditions. For example: `value = 33.03`, `floor(value) = 33`, `searchAmount = 33.03`, `floor(searchAmount) = 33`; Like this you can develop your scenarios. – mayank bisht Oct 11 '17 at 11:17
  • "Now to define correct," ... proceeds to define correct as either 33 or 33.03. – Rotem Oct 11 '17 at 11:17
  • I added three specific scenarios, hope this is better. – miniHessel Oct 11 '17 at 11:21
  • https://stackoverflow.com/a/580252/7974050 – Amit Kumar Singh Oct 11 '17 at 11:24
  • 1
    This is more of a UX question. Personally I would expect to have *from* and *to* fields when filtering by an amount, rather than a single field. – Rotem Oct 11 '17 at 11:27
  • Actually, this specific search is when a customer comes back with a bank receipt, and you know the specific amount. I just want to include cases when the employee is lazy. – miniHessel Oct 11 '17 at 11:28
  • "employee is lazy" in entering banking data? are you sure? What is the purpose of this code? – Amit Kumar Singh Oct 11 '17 at 11:33
  • @miniHessel In that case I would use a threshold depending on the number of digits the employee entered, e.g. for "33" return 33.00 - 33.99, for "33.0" return 33.00 - 33.09 and for "33.03" return only 33.03. – Rotem Oct 11 '17 at 11:35
  • @amit This is a search. When the customer comes back, and says "I have a problem with the product I purchased, and it's not purchased on a registered customer, searching for the amount on the bank receipt is a great function. This is a retail brick and mortar store scenario, so some customers choose to not register themselves. – miniHessel Oct 11 '17 at 11:36
  • @miniHessel Check my answer, if you want to allow difference upto 0.99, you can use that. – Amit Kumar Singh Oct 11 '17 at 11:37
  • 2
    @Amit Foolproofing is always a good idea. – Rotem Oct 11 '17 at 11:38
  • Am I missing something or shouldn't we just be comparing `int`s? – DiskJunky Oct 11 '17 at 11:51

6 Answers6

1

Use your if condition like this. Round to 2 decimal places and compare.

     if((Math.Round(order.amount,2) - Math.Round(searchAmount,2)) <= 0.9M)

    {
      addOrderToList();

    }
Amit Kumar Singh
  • 4,393
  • 2
  • 9
  • 22
1

If you want to discard the fractional part completely, using a combination of LINQ and Math.Truncate

var orders = listOfOrders.Where(o => Math.Truncate(o.amount) == Math.Truncate(searchAmount))
                         .ToList();

Math.Truncate returns the integral part of a given decimal, Where selects only appropriate orders (do read up on LINQ's deferred execution if you don't know it) and ToList materializes the query into a list.

EDIT: given your edit, this is probably what you're looking for:

var orders
   = listOfOrders.Where(
      o => Math.Truncate(o.amount) == Math.Truncate(searchAmount)
        && o.amount.ToString(CultureInfo.InvariantCulture)
                   .StartsWith(searchAmount.ToString(CultureInfo.InvariantCulture)))
                 .ToList();

This first verifies if the integral part of the numbers match and then uses string comparison to check if the actual amount starts with what was inputted (by your lazy user).

decPL
  • 5,384
  • 1
  • 26
  • 36
  • If Math.Truncate would already convert it to no decimal place, and compare it correctly, why add another && condition doing the same thing? – Amit Kumar Singh Oct 11 '17 at 11:42
  • Because, if I'm reading the requirements correctly (I admit there's certain degree of guessing here, OP really isn't clear on these), you shouldn't match an order with amount `33.00` if your search amount was `33.9`, but you should match one with amount `33.95` for example. – decPL Oct 11 '17 at 11:47
  • On the other hand, you can't drop the `Truncate` part, otherwise search amount `3` would find orders with amount `33` for example. – decPL Oct 11 '17 at 11:49
  • 1
    Good comeback on the explanation part. – Amit Kumar Singh Oct 11 '17 at 11:50
0

What if you use Math.Truncate(number)? Just like:

if(Math.Truncate(order.amount) == Math.Truncate(searchAmount))
FcoRodr
  • 1,583
  • 7
  • 15
0

You need to use Math.Floor method to match all numbers i.e absolute value

decimal searchAmount = 33.03;
var temp = Math.Floor(searchAmount);
foreach (var order in listOforders)
{ 
  if(Math.Floor(order.amount) == temp)
  {
    addOrderToList()
  }
} 
Ipsit Gaur
  • 2,872
  • 1
  • 23
  • 38
0

If am right you need to do define some maximum difference constant and use it something like that

decimal maxDiff = 0.03;
decimal searchAmount = 33.03;
var result =  listOfOrders.Where(o => Math.Abs(o.Amount - searchAmount) <=  maxDiff);
Stas Petrov
  • 315
  • 5
  • 17
0

There is no need for any call to Math as a cast to int will do the same. Your code could be changed to;

int searchAmount = 33;
listOforders.Where(o => (int)o.Amount == searchAmount)
            .ForEach(o => addOrderToList());
DiskJunky
  • 4,750
  • 3
  • 37
  • 66