международный массив для строкового представления

Интерфейс является контрактом, которого придерживаются все классы с реализацией. Это означает, что они должны придерживаться всего этого или ни одного из него.

, Если бы интерфейс общедоступен тогда, каждая часть того контакта должна быть общедоступной, иначе это значило бы тот для друга классы / внутренние классы и другая вещь для всего остального.

Или используйте абстрактный базовый класс или (если возможный и практичный) метод внутреннего добавочного номера в интерфейсе .

55
задан John Rudy 30 November 2009 в 22:38
поделиться

9 ответов

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

var builder = new StringBuilder();
Array.ForEach(arr, x => builder.Append(x));
var res = builder.ToString();
20
ответ дан 26 November 2019 в 17:38
поделиться

at.net 3.5 use:

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

at.net 4.0 или выше используйте: (см. Ответ @Jan Remunda)

 string result = string.Join("", array);
88
ответ дан 26 November 2019 в 17:38
поделиться
string result = arr.Aggregate("", (s, i) => s + i.ToString());

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

10
ответ дан 26 November 2019 в 17:38
поделиться

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.

5
ответ дан 26 November 2019 в 17:38
поделиться

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();     
5
ответ дан 26 November 2019 в 17:38
поделиться
string.Join("", (from i in arr select i.ToString()).ToArray())

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

string.Join("", from i in arr select i.ToString())
1
ответ дан 26 November 2019 в 17:38
поделиться

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());
1
ответ дан 26 November 2019 в 17:38
поделиться

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

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

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

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

Если мне нужно беспокоиться о том, что массив является нулевым, теперь он становится таким:

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

Но если вы ' вы все равно собираетесь поместить его в служебную функцию, действительно ли вам нужно, чтобы он был сжат до однострочника? В таком случае почему бы не добавить несколько дополнительных строк для ясности и не воспользоваться 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');
24
ответ дан 26 November 2019 в 17:38
поделиться

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')));
1
ответ дан 26 November 2019 в 17:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: