programing

int 배열을 문자열로

sourcetip 2021. 1. 16. 11:14
반응형

int 배열을 문자열로


C #에서는 숫자 만 포함하는 int 배열이 있습니다. 이 배열을 문자열로 변환하고 싶습니다.

배열 예 :

int[] arr = {0,1,2,3,0,1};

이것을 다음과 같은 형식의 문자열로 어떻게 변환 할 수 "012301"있습니까?


at.net 3.5 사용 :

 String.Join("", new List<int>(array).ConvertAll(i => i.ToString()).ToArray());

at.net 4.0 이상 사용 : (@Jan Remunda의 답변 참조)

 string result = string.Join("", array);

String.Join 함수를 간단히 사용할 수 있으며 내부적으로 사용 string.Empty하기 때문에 구분 기호로 사용할 수 있습니다 StringBuilder.

string result = string.Join(string.Empty, new []{0,1,2,3,0,1});

예 : 세미콜론을 구분 기호로 사용하면 결과는 0;1;2;3;0;1.

실제로는 null 구분 기호와 함께 작동하며 두 번째 매개 변수는 다음과 같이 모든 개체를 열거 할 수 있습니다.

string result = string.Join(null, new object[]{0,1,2,3,0,"A",DateTime.Now});

내 의견이 인기가 없을 수도 있다는 것을 알고 있지만 Linq-y 밴드 왜건에 뛰어 드는 것이 힘든 것 같습니다. 멋지다. 응축되어 있습니다. 나는 그것을 얻었고 적절한 곳에서 그것을 사용하는 것에 반대하지 않습니다. 나뿐일지도 모르지만, 사람들은 원하는 것을 달성하기 위해 유틸리티 함수를 만드는 것에 대해 생각하는 것을 멈추고 대신 고밀도 1- 라이너를 만들기 위해 지나치게 긴 라인의 Linq 코드로 코드를 버리는 것을 선호하는 것 같습니다.

사람들이 여기에 제공 한 Linq 답변이 나쁘다는 말은 아니지만 다양한 상황을 처리해야 할 때 이러한 단일 코드 줄이 길어지고 더 모호해질 수있는 잠재력이 있다고 생각합니다. . 배열이 null이면 어떻게됩니까? 순전히 연결되는 대신 구분 된 문자열을 원하면 어떨까요? 배열의 정수 중 일부가 두 자리이고 각 요소의 문자열이 나머지와 동일한 길이가되도록 각 값을 선행 0으로 채우려면 어떻게해야합니까?

제공된 답변 중 하나를 예로 들면 :

        result = arr.Aggregate(string.Empty, (s, i) => s + i.ToString());

배열이 null 인 것에 대해 걱정해야한다면 이제 다음과 같이됩니다.

        result = (arr == null) ? null : arr.Aggregate(string.Empty, (s, i) => s + i.ToString());

쉼표로 구분 된 문자열을 원하면 다음과 같이됩니다.

        result = (arr == null) ? null : arr.Skip(1).Aggregate(arr[0].ToString(), (s, i) => s + "," + i.ToString());

이것은 여전히 ​​나쁘지 않지만이 코드 줄이 무엇을하는지 한눈에 명확하지 않다고 생각합니다.

물론,이 코드 줄을 자신의 유틸리티 함수에 넣는 것을 막을 수는 없으므로 특히 여러 곳에서 수행하는 경우 응용 프로그램 논리와 긴 혼란을 일으키지 않습니다.

    public static string ToStringLinqy<T>(this T[] array, string delimiter)
    {
        // edit: let's replace this with a "better" version using a StringBuilder
        //return (array == null) ? null : (array.Length == 0) ? string.Empty : array.Skip(1).Aggregate(array[0].ToString(), (s, i) => s + "," + i.ToString());
        return (array == null) ? null : (array.Length == 0) ? string.Empty : array.Skip(1).Aggregate(new StringBuilder(array[0].ToString()), (s, i) => s.Append(delimiter).Append(i), s => s.ToString());
    }

그러나 어쨌든 유틸리티 기능에 넣으려면 실제로 1 라이너로 압축해야합니까? 이 경우 명확성을 위해 몇 줄을 추가하고 StringBuilder를 활용하여 반복적 인 연결 작업을 수행하지 않는 이유는 무엇입니까?

    public static string ToStringNonLinqy<T>(this T[] array, string delimiter)
    {
        if (array != null)
        {
            // edit: replaced my previous implementation to use StringBuilder
            if (array.Length > 0)
            {
                StringBuilder builder = new StringBuilder();

                builder.Append(array[0]);
                for (int i = 1; i < array.Length; i++)
                {
                    builder.Append(delimiter);
                    builder.Append(array[i]);
                }

                return builder.ToString()
            }
            else
            {
                return string.Empty;
            }
        }
        else
        {
            return null;
        }
    }

성능에 대해 정말 걱정이된다면 string.Join을 수행할지 아니면 배열에있는 요소 수에 따라 StringBuilder를 사용할지 결정하는 하이브리드 함수로 전환 할 수도 있습니다 (이것은 마이크로 최적화입니다. 내 의견으로는 할 가치가 없으며 유익한 것보다 더 해로울 수 있지만이 문제의 예로 사용하고 있습니다.)

    public static string ToString<T>(this T[] array, string delimiter)
    {
        if (array != null)
        {
            // determine if the length of the array is greater than the performance threshold for using a stringbuilder
            // 10 is just an arbitrary threshold value I've chosen
            if (array.Length < 10)
            {
                // assumption is that for arrays of less than 10 elements
                // this code would be more efficient than a StringBuilder.
                // Note: this is a crazy/pointless micro-optimization.  Don't do this.
                string[] values = new string[array.Length];

                for (int i = 0; i < values.Length; i++)
                    values[i] = array[i].ToString();

                return string.Join(delimiter, values);
            }
            else
            {
                // for arrays of length 10 or longer, use a StringBuilder
                StringBuilder sb = new StringBuilder();

                sb.Append(array[0]);
                for (int i = 1; i < array.Length; i++)
                {
                    sb.Append(delimiter);
                    sb.Append(array[i]);
                }

                return sb.ToString();
            }
        }
        else
        {
            return null;
        }
    }

이 예의 경우 성능에 미치는 영향은 신경 쓸 가치가 없을 것입니다. 그러나 요점은 실제로 작업 성능에 대해 관심을 가져야하는 상황에있는 경우에는 복잡한 Linq 표현식을 사용하는 것보다 유틸리티 함수 내에서 처리하는 것이 더 쉽고 읽기 쉽습니다.

그 유틸리티 함수는 여전히 다소 어색해 보입니다. 이제 하이브리드를 버리고 이렇게합시다.

    // convert an enumeration of one type into an enumeration of another type
    public static IEnumerable<TOut> Convert<TIn, TOut>(this IEnumerable<TIn> input, Func<TIn, TOut> conversion)
    {
        foreach (TIn value in input)
        {
            yield return conversion(value);
        }
    }

    // concatenate the strings in an enumeration separated by the specified delimiter
    public static string Delimit<T>(this IEnumerable<T> input, string delimiter)
    {
        IEnumerator<T> enumerator = input.GetEnumerator();

        if (enumerator.MoveNext())
        {
            StringBuilder builder = new StringBuilder();

            // start off with the first element
            builder.Append(enumerator.Current);

            // append the remaining elements separated by the delimiter
            while (enumerator.MoveNext())
            {
                builder.Append(delimiter);
                builder.Append(enumerator.Current);
            }

            return builder.ToString();
        }
        else
        {
            return string.Empty;
        }
    }

    // concatenate all elements
    public static string ToString<T>(this IEnumerable<T> input)
    {
        return ToString(input, string.Empty);
    }

    // concatenate all elements separated by a delimiter
    public static string ToString<T>(this IEnumerable<T> input, string delimiter)
    {
        return input.Delimit(delimiter);
    }

    // concatenate all elements, each one left-padded to a minimum length
    public static string ToString<T>(this IEnumerable<T> input, int minLength, char paddingChar)
    {
        return input.Convert(i => i.ToString().PadLeft(minLength, paddingChar)).Delimit(string.Empty);
    }

Now we have separate and fairly compact utility functions, each of which are arguable useful on their own.

Ultimately, my point is not that you shouldn't use Linq, but rather just to say don't forget about the benefits of creating your own utility functions, even if they are small and perhaps only contain a single line that returns the result from a line of Linq code. If nothing else, you'll be able to keep your application code even more condensed than you could achieve with a line of Linq code, and if you are using it in multiple places, then using a utility function makes it easier to adjust your output in case you need to change it later.

For this problem, I'd rather just write something like this in my application code:

        int[] arr = { 0, 1, 2, 3, 0, 1 };

        // 012301
        result = arr.ToString<int>();

        // comma-separated values
        // 0,1,2,3,0,1
        result = arr.ToString(",");

        // left-padded to 2 digits
        // 000102030001
        result = arr.ToString(2, '0');

To avoid the creation of an extra array you could do the following.

var builder = new StringBuilder();
Array.ForEach(arr, x => builder.Append(x));
var res = builder.ToString();

string result = arr.Aggregate("", (s, i) => s + i.ToString());

(Disclaimer: If you have a lot of digits (hundreds, at least) and you care about performance, I suggest eschewing this method and using a StringBuilder, as in JaredPar's answer.)


You can do:

 int[] arr = {0,1,2,3,0,1};
 string results = string.Join("",arr.Select(i => i.ToString()).ToArray());

That gives you your results.


I like using StringBuilder with Aggregate(). The "trick" is that Append() returns the StringBuilder instance itself:

var sb = arr.Aggregate( new StringBuilder(), ( s, i ) => s.Append( i ) );
var result = sb.ToString();     

string.Join("", (from i in arr select i.ToString()).ToArray())

In the .NET 4.0 the string.Join can use an IEnumerable<string> directly:

string.Join("", from i in arr select i.ToString())

I've left this here for posterity but don't recommend its use as it's not terribly readable. This is especially true now that I've come back to see if after a period of some time and have wondered what I was thinking when I wrote it (I was probably thinking 'crap, must get this written before someone else posts an answer'.)

string s = string.Concat(arr.Cast<object>().ToArray());

The most efficient way is not to convert each int into a string, but rather create one string out of an array of chars. Then the garbage collector only has one new temp object to worry about.

int[] arr = {0,1,2,3,0,1};
string result = new string(Array.ConvertAll<int,char>(arr, x => Convert.ToChar(x + '0')));

If this is long array you could use

var sb = arr.Aggregate(new StringBuilder(), ( s, i ) => s.Append( i ), s.ToString());

ReferenceURL : https://stackoverflow.com/questions/1822811/int-array-to-string

반응형