3
\$\begingroup\$

Given the length of an array and a char, I would like to replace every element in a char array with that given char.

Using a for loop, I'm changing each element to that char. Is there a better way to do it, or a specific method for that?

using System;
using System.Collections.Generic;

namespace TestProject
{
    class Solution
    {
        static void TestMethod()
        {
            //lines of code
            int lengthOfArray = int.Parse(Console.ReadKey());
            char charReplace = Console.ReadKey().KeyChar;

            char[] arrayChar = new char[lengthOfArray];
            for (int i = 0; i < lengthOfArray; i++)
            {
                arrayChar[i] = charReplace;
            }
        }
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ This is example code, ins't it ? \$\endgroup\$
    – Heslacher
    Commented Jan 30, 2015 at 7:56
  • \$\begingroup\$ Nope, quickly made in in Visual Studio 2013. Its not in my actual program (which I will show soon for dissection) ;) \$\endgroup\$ Commented Jan 30, 2015 at 7:58
  • 1
    \$\begingroup\$ Is the question meant to be general or specific to a char array ? \$\endgroup\$
    – Heslacher
    Commented Jan 30, 2015 at 7:59
  • \$\begingroup\$ Any array, not just char \$\endgroup\$ Commented Jan 30, 2015 at 8:14

3 Answers 3

7
\$\begingroup\$

You can also use the static Array.Fill to quickly initialize an array to a given value:

bool[] isPrime = new bool[500];
Array.Fill(isPrime, true);

This will set all items in the array to true.

As mentioned in the comments by Pieter Witvoet, this feature is available in .NET Core only.

\$\endgroup\$
2
  • \$\begingroup\$ You may want to mention that this is only available in .NET Core. \$\endgroup\$ Commented Jan 8, 2019 at 15:04
  • \$\begingroup\$ Oh, that is the reason I didn't see it in the previous answers... Thank you for pointing it out! \$\endgroup\$ Commented Jan 8, 2019 at 15:11
4
\$\begingroup\$

You shouldn't put the input reading and creating the array into one method, because this is violating the single responsibility principle which

Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change. As an example, consider a module that compiles and prints a report. Such a module can be changed for two reasons. First, the content of the report can change. Second, the format of the report can change. These two things change for very different causes; one substantive, and one cosmetic. The single responsibility principle says that these two aspects of the problem are really two separate responsibilities, and should therefore be in separate classes or modules. It would be a bad design to couple two things that change for different reasons at different times.

SRP means that each method should be responsible for one thing only. So your method is doing to much. It is reading input from the user and also is creating the array.


Methods should be named by using meaningful names. This isn't the case for TestMethod.


charReplace isn't a good name, because you don't replace but initialize each element.


Basically the using of a for loop is the best way to achieve the desired goal. Another way would be to use the String's overloaded constructor and then calling ToCharArray() on the created string.

public static char[] GetInitializedArray(int length, char initialValue)
{
    return (new String(initialValue, length)).ToCharArray();
}  

By using a for loop this method could be made generic. In this way you could use the method to create initialized arrays of any type you need.

This would look like

public static T[] GetInitializedArray<T>(int length, T initialValue)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    {
        result[i] = initialValue;
    }
    return result;
}  

and can be used like

char[] values = GetInitializedArray<char>(10, 'Y');  
\$\endgroup\$
6
  • \$\begingroup\$ Thank you for that. The beginning three don't really apply since I just made those names for this example, but the last one definately does. Thanks again :D \$\endgroup\$ Commented Jan 30, 2015 at 8:15
  • \$\begingroup\$ Could you explain the single responsibility principle? I am new to coding, and I have a bunch of small methods, but one MASSIVE class. How are you meant to use it otherwise? \$\endgroup\$ Commented Jan 30, 2015 at 8:17
  • \$\begingroup\$ Updated answer. \$\endgroup\$
    – Heslacher
    Commented Jan 30, 2015 at 8:23
  • \$\begingroup\$ Thank you. I do this for methods, but not for classes. Does it apply to that aswell? \$\endgroup\$ Commented Jan 30, 2015 at 8:29
  • \$\begingroup\$ Yes this also applies for classes, but usually you can't always prevent to violate the SRP. Only using one massive class for everything is also reffered to as God object which usually is a anti pattern. \$\endgroup\$
    – Heslacher
    Commented Jan 30, 2015 at 8:31
4
\$\begingroup\$

Probably the easiest, and most C#-idiomatic way to do this is to use the in-built function:

Enumerable.Repeat(charReplace, lengthOfArray);

If you specifically need this in an array rather than a general IEnumerable<char>, you can simply add:

Enumerable.Repeat(charReplace, lengthOfArray).ToArray();

In C#, in general you should use these kinds of enumerable-manipulating methods (found in the System.Linq namespace) instead of loops as your first port of call. They usually lead to terser, easier to read code. Only occasionally are loops easier to read.


Beyond this, I have to echo Heslacher on both the issues with naming and with this method mixing its responsibilities. In fact, these issues are linked, because taking care with your naming is often the best early-warning mechanism for a method doing too much, or lacking a single purpose.

For example, what should this method be called? GetInitializedArray as Heslacher suggests is nice, but doesn't actually describe your initial method well, because it gives no indication that it's also going to be doing IO.

GetInitializedArrayFromConsoleInput would be a more accurate name, and this should immediately raise alarm bells: Why is this description so long? Why does it combine two unrelated concepts (initializing an array and console IO)? The answer is that the method lacks a single purpose (or "responsibility"), and should be separated out.


lengthOfArray and charReplace are okay names, but not great. Both seem to put too much focus on the data-types involved. This method is simple enough that that's probably not a big problem, but in general your emphasis should be on what you're trying to do, not how you're trying to do it. I can't think of better names than length and initialValue from Heslacher's answer.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.