简体   繁体   中英

Simplify list.add of unknown amount of entries

So I am currently working on a calculator.

One of the requirements is to store the history, which I currently do in a list.

While I have simplified alot of code I can't get my head around simplifying this

           if (amountNumbers == 2)
            {
                memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " = " + calculation.ToString());
                userNumbers.Clear();
            }
            if (amountNumbers == 3)
            {
                memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " " + op + " " + userNumbers[2].ToString() + " = " + calculation.ToString());
                userNumbers.Clear();
            }
            if (amountNumbers == 4)
            {
                memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " " + op + " " + userNumbers[2].ToString() + " " + op + " " + userNumbers[3].ToString() + " = " + calculation.ToString());
                userNumbers.Clear();
            }
            if (amountNumbers == 5)
            {
                memory.Add(userNumbers[0].ToString() + " " + op + " " + userNumbers[1].ToString() + " " + op + " " + userNumbers[2].ToString() + " " + op + " " + userNumbers[3].ToString() + " " + op + " " + userNumbers[4].ToString() + " = " + calculation.ToString());
                userNumbers.Clear();
            }

Any idea how I simplify this and make the adding dynamic depending on how many values the user has chosen? Preferably I want to store the whole string within one index since that is how the history is being displayed.

Easy, loop over userNumbers and build your string, then add it to memory once you're done. Like so:

// Ensure that we don't get an 'IndexOutOfBoundsException'
// By clamping  'amountNumbers' to the length if 'userNumbers' if it's larger
if (amountNumbers > userNumbers.Length)
    amountNumbers = userNumbers.Length;

// You could use a normal 'string' and '... += ...' but 'StringBuilder' is more efficient
var sb = new StringBuilder();
for (int i = 0; i < amountNumbers; i++)
    sb.Append($"{userNumbers[i].ToString()} ");

// Add the calculation, no space at the start required as the loop adds a trailing space
sb.Append($"= {calculation.ToString()}");

memory.Add(sb.ToString());

Use .Take(amountNumbers) to get at most amountNumbers of user numbers, . And String.Join to combine strings with some separator between each:

var users = userNumbers.Take(amountNumbers).Select(s => s.ToString());
var str = string.Join(" " + op + " ", users);
memory.Add(str + " = " + calculation.ToString());

If you need some special handling for cases, like if amountNumbers< userNumbers.Count or amountNumbers == 1 you need to add that separately. If you know that amountNumbers == userNumbers.Count , then the .Take(...) is not needed.

You can just Join userNumbers values with " " + op + " " separator, then concat calculation at end:

string lastExpression = string.Join(" " + op + " ", userNumbers) + // Join values
                        " = " + calculation.ToString(); // Concat calculation result
memory.Add(lastExpression);
userNumbers.Clear();

There is no matter which amount of values in userNumbers - they all will be joined with " " + op + " " between each other.

Shorter version with string interpolation:

memory.Add($"{string.Join($" {op} ", userNumbers)} = {calculation}");
userNumbers.Clear();

EDIT. This is very similar idea with @JonasH 's answer, just without converting userNumbers to a collection of strings. Join makes it implicitly at behind.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM