0

I am receiving a csv string that I need to display in a .Net6.0 wpf ListView. I'm processing thousands of strings per second, and would like a quick way to truncate a string after the decimal for six of the values in the string. I know that I can convert to a number, but this seems bulky, especially since I would have to convert back to string for display. Here is my function:

public void AddComponent(string component)
{
    Component newcomp = new Component();
    string[] items = component.Split(',');
    newcomp.Time = items[0].Substring(items[0].IndexOf(':') + 1);
    newcomp.CompId = items[1];
    newcomp.Range = items[2].Substring(0, items[2].IndexOf('.') + 3);
    newcomp.Diameter = items[3].Substring(0, items[3].IndexOf('.') + 3);
    newcomp.Radius = items[4].Substring(0, items[4].IndexOf('.') + 3);
    newcomp.Height = items[5];
    newcomp.Validity = EnumExtensions.GetDescription((ComponentValidity)(ushort.Parse(items[6])));
    newcomp.Value = items[7];
    newcomp.RCS = items[8];
    newcomp.Status = EnumExtensions.GetDescription((ComponentStatus)ushort.Parse(items[9].Substring(0, 1)));
    newcomp.Confidence = EnumExtensions.GetDescription((ComponentConfidence)ushort.Parse(items[9].Substring(3, 1)));
    newcomp.MNF = items[10].Substring(0, items[10].IndexOf('.') + 3);
    newcomp.Group = items[11];
    newcomp.Classification = EnumExtensions.GetDescription((ComponentClassification)(ushort.Parse(items[12])));
    newcomp.Serial = items[13];
    newcomp.ShelfNumber = items[14].Substring(0, items[14].IndexOf('.') + 3);
    newcomp.HYT = items[15].Substring(0, items[15].IndexOf('.') + 3);
    Components.Add(newcomp);
}

The main ones I'm concerned about are the six that do this:

items[x].Substring(0, items[x].IndexOf('.') + 3);

These numbers can look like:

34.2
34.24
34.2456
76765.2232

I want the end result to be

34.2
34.24
34.24
76765.22

And of course the problem is the + 3 on the end of the line because sometimes there aren't enough characters to fill that out.

I'm already parsing some of the items to get the enum values, so I would rather not convert these strings to a decimal and back again. Is there an easy one-liner that might accomplish this?

ASh
  • 34,632
  • 9
  • 60
  • 82
Alexa Kirk
  • 152
  • 10
  • What version of .NET are you using? – Matthew Watson Jun 08 '23 at 13:44
  • See; [How do I truncate a .NET string?](https://stackoverflow.com/q/2776673/880990). But this is going to be bulkier than converting to decimal and formatting: `((decimal)items[x]).ToString("F2")`. See: [Standard numeric format strings](https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings) and [Custom numeric format strings](https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings). – Olivier Jacot-Descombes Jun 08 '23 at 13:47
  • 1
    You could just use `number.Substring(0, Math.Min(number.Length, number.IndexOf('.') + decimals + 1));` – Matthew Watson Jun 08 '23 at 13:54
  • @OlivierJacot-Descombes Thanks for the links, but I'm not truncating the entire string, just the part after the decimal point. Also the Standard numeric format strings are for converting to strings, but it is already a string and I would prefer not to convert. – Alexa Kirk Jun 08 '23 at 13:55
  • Exactly what I was looking for, @MatthewWatson! Thanks! – Alexa Kirk Jun 08 '23 at 14:03
  • Although the code I posted does NOT handle the case where there is no '.' at all, so watch out for that. It will truncate a dotless string to `decimals` length. – Matthew Watson Jun 08 '23 at 14:10
  • I wouldn't assume converting from string -> number -> string will perform poorly unless you test it for performance. – StayOnTarget Jun 08 '23 at 14:32

2 Answers2

0

I figured out a two-liner that works pretty well:

int index = items[2].IndexOf('.');
newcomp.Range = items[2].Substring(0, index + (items[2].Length - index > 3 ? 3 : items[2].Length - index));

EDIT

Combining Matthew Watson's samples with this two-line approach, and taking into account there may not be a decimal point at all, I get:

int index = items[2].IndexOf('.');
newcomp.Range = index == -1 ? items[2] : items[2][..Math.Min(items[2].Length, index + 3)];
Alexa Kirk
  • 152
  • 10
  • 2
    Alternatively in one line: `newcomp.Range = items[2].Substring(0, Math.Min(items[2].Length, items[2].IndexOf('.') + decimals + 1));` - I'd put that in a method for readability though. – Matthew Watson Jun 08 '23 at 13:56
0

Perhaps something like this? var tempNumber = items[x]+"0"; tempNumber.Substring(0, itempNumber.IndexOf('.') + 3);

Sasi
  • 1
  • 2
  • Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. **Would you kindly [edit] your answer to include additional details for the benefit of the community?** – Jeremy Caney Jun 09 '23 at 00:57