Подтвердить что ты не робот

Int array to string

В С# у меня есть массив ints, содержащий только цифры. Я хочу преобразовать этот массив в строку.

Пример массива:

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

Как я могу преобразовать это в строку, отформатированную как: "012301"?

4b9b3361

Ответ 1

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);

Ответ 2

Вы можете просто использовать функцию String.Join, а в качестве разделителя использовать string.Empty потому что он использует StringBuilder внутреннего использования.

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

Например: если вы используете точку с запятой в качестве разделителя, результат будет 0;1;2;3;0;1.

На самом деле он работает с нулевым разделителем, а второй параметр может быть перечисляемым для любых объектов, например:

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

Ответ 3

Я понимаю, что мое мнение, вероятно, не популярное, но я думаю, что мне трудно перепрыгивать на фургон Linq-y. Это изящно. Он сжался. Я получаю это, и я не против использования его там, где это уместно. Возможно, это только я, но я чувствую, что люди перестали думать о создании функций полезности, чтобы выполнить то, что они хотят, и вместо этого предпочитают засорять свой код (иногда) чрезмерно длинными строками кода Linq ради создания плотного 1-лайнера.

Я не говорю, что любой из ответов Linq, которые люди здесь предоставили, плохи, но я думаю, что я чувствую, что существует вероятность того, что эти отдельные строки кода могут стать более длинными и более неясными, поскольку вам нужно обрабатывать различные ситуации. Что делать, если ваш массив равен нулю? Что делать, если вы хотите иметь строчную разделительную строку, а не просто конкатенированную? Что делать, если некоторые из целых чисел в вашем массиве являются двузначными, и вы хотите поместить каждое значение с ведущими нулями, чтобы строка для каждого элемента была такой же длины, как и остальные?

В качестве примера возьмем один из предоставленных ответов:

        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 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);
    }

Теперь у нас есть отдельные и довольно компактные служебные функции, каждый из которых может быть полезен сам по себе.

В конечном счете, моя точка зрения заключается не в том, что вы не должны использовать Linq, а просто для того, чтобы сказать, не забывайте о преимуществах создания ваших собственных функций полезности, даже если они небольшие и, возможно, содержат только одну строку, которая возвращает результат из строки кода Linq. Если ничего другого, вы сможете сохранить код приложения еще более сжатым, чем вы могли бы достичь с помощью строки кода Linq, и если вы используете его в нескольких местах, то использование функции утилиты упрощает настройку вашего вывода если вам нужно изменить его позже.

Для этой проблемы я бы скорее написал что-то вроде этого в коде приложения:

        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');

Ответ 4

Чтобы избежать создания дополнительного массива, вы можете сделать следующее.

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

Ответ 5

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

(Отказ от ответственности: если у вас есть много цифр (по меньшей мере, сотни), и вы заботитесь о производительности, я предлагаю отказаться от этого метода и использовать StringBuilder, как в ответе JaredPar.)

Ответ 6

Вы можете сделать:

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

Это дает вам ваши результаты.

Ответ 7

Мне нравится использовать StringBuilder с Aggregate(). "Трюк" заключается в том, что Append() возвращает сам экземпляр StringBuilder:

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

Ответ 8

Я оставил это здесь для потомков, но не рекомендую его использовать, так как он не очень читаем. Это особенно верно сейчас, когда я вернулся, чтобы увидеть, если после некоторого времени и подумать, о чем я думал, когда писал (я, вероятно, думал "дерьмо", должен написать это, прежде чем кто-то еще ответит ",.)

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

Ответ 9

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

В .NET 4.0 string.Join может напрямую использовать IEnumerable<string>:

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

Ответ 10

Самый эффективный способ - не преобразовывать каждое int в строку, а создать одну строку из массива символов. Тогда у сборщика мусора будет только один новый временный объект.

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

Ответ 11

Если это длинный массив, вы можете использовать

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