Как присоединить int [] к строке, разделенной символами в .NET?

У меня есть массив целых чисел:

int[] number = new int[] { 2,3,6,7 };

Как проще всего преобразовать их в одну строку, в которой числа разделены символом (например, "2,3,6,7")?

Я использую C# и .NET 3.5.

ТАК классно! Я получил эти 3 отличных ответа за 10 минут в воскресенье!

Riri 28.09.2008 17:54

Начиная с .NET 4.0, есть методы, которые принимают массив объектов и IEnumerable, поэтому вы можете просто использовать string.join(",", number). Я знаю, что в вопросе указывается .NET 3.5, поэтому я не давал этого ответа, но он появляется в поисках, которые не указывают версию, и знание того, что это возможно в 4.0, может кому-то помочь.

Jason Goemaat 24.02.2015 00:06
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
101
2
63 372
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Ответ принят как подходящий

var ints = new int[] {1, 2, 3, 4, 5};
var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());
Console.WriteLine(result); // prints "1,2,3,4,5"

РЕДАКТИРОВАТЬ: Начиная с (по крайней мере) .NET 4.5,

var result = string.Join(",", ints.Select(x => x.ToString()).ToArray());

эквивалентно:

var result = string.Join(",", ints);

РЕДАКТИРОВАТЬ:

Я вижу, что несколько решений рекламируют использование StringBuilder. Кто-то жалуется, что метод Join должен принимать аргумент IEnumerable.

Я вас разочарую :) String.Join требует массив только по одной причине - производительности. Метод соединения должен знать размер данных для эффективного предварительного выделения необходимого объема памяти.

Вот часть внутренней реализации метода String.Join:

// length computed from length of items in input array and length of separator
string str = FastAllocateString(length);
fixed (char* chRef = &str.m_firstChar) // note than we use direct memory access here
{
    UnSafeCharBuffer buffer = new UnSafeCharBuffer(chRef, length);
    buffer.AppendString(value[startIndex]);
    for (int j = startIndex + 1; j <= num2; j++)
    {
        buffer.AppendString(separator);
        buffer.AppendString(value[j]);
    }
}

Мне лень сравнивать производительность предложенных методов. Но что-то мне подсказывает, что победит Join :)

Вероятно, это лучший вариант использования основных методов расширения .NET, но мне очень хотелось, чтобы string.Join () принимала IEnumerable <string>, чтобы избежать преобразования ToArray ().

spoulson 28.09.2008 18:43

Ничто не мешает кому-то перегрузить строку. Присоединяйтесь, чтобы взять IEnumerable. ;)

Robert P 20.10.2008 23:57

Это, вероятно, также самое простое решение, а не только самое быстрое.

Dave Van den Eynde 22.10.2008 14:40

.NET 4 предоставляет перегрузку String.Join, которая принимает IEnumerable в качестве параметра. msdn.microsoft.com/en-us/library/dd783876.aspx

Ryan Kohn 27.06.2011 23:03

using System.Linq; не требуется.

Gayan Weerakutti 05.12.2018 17:24

String.Join(";", number.Select(item => item.ToString()).ToArray());

Мы должны преобразовать каждый из элементов в String, прежде чем мы сможем присоединиться к ним, поэтому имеет смысл использовать Select и лямбда-выражение. Это эквивалент map на некоторых других языках. Затем мы должны преобразовать полученную коллекцию строк обратно в массив, потому что String.Join принимает только массив строк.

Я считаю, что ToArray() немного уродлив. String.Join действительно должен принимать IEnumerable<String>, нет причин ограничивать его только массивами. Вероятно, это связано с тем, что Join - это еще до дженериков, когда массивы были единственным доступным типом коллекции.

Если ваш массив целых чисел может быть большим, вы получите лучшую производительность, используя StringBuilder. Например.:

StringBuilder builder = new StringBuilder();
char separator = ',';
foreach(int value in integerArray)
{
    if (builder.Length > 0) builder.Append(separator);
    builder.Append(value);
}
string result = builder.ToString();

Обновлено: когда я опубликовал это, у меня сложилось ошибочное впечатление, что «StringBuilder.Append (int value)» внутренне удалось добавить строковое представление целочисленного значения без создания строкового объекта. Это неправильно: проверка метода с помощью Reflector показывает, что он просто добавляет value.ToString ().

Поэтому единственное возможное различие в производительности заключается в том, что этот метод позволяет избежать создания одного массива и немного раньше освобождает строки для сборки мусора. На практике это не будет иметь никакого измеримого значения, поэтому я проголосовал за это лучшее решение.

Вы измерили, чтобы он был быстрее? String.Join также использует StringBuilder.

JacquesB 28.09.2008 18:37

Да, но сначала нужно преобразовать все в массив, что далеко от идеала. В частности, это означает, что вам нужно иметь все преобразованные строки в памяти одновременно, до вы начинаете строить результирующую строку.

Jon Skeet 28.09.2008 18:46

OTOH String.Join предварительно вычисляет размер буфера StringBuilder, чтобы избежать изменения размера. Так что это может быть быстрее, даже если для этого потребуется больше памяти.

JacquesB 29.09.2008 00:08

Одним из сочетаний этих двух подходов было бы написание метода расширения для IEnumerable <T>, который использовал бы StringBuilder. Вот пример с разными перегрузками в зависимости от того, хотите ли вы указать преобразование или просто полагаться на простой ToString. Я назвал метод «JoinStrings» вместо «Join», чтобы избежать путаницы с другим типом Join. Может, кто-нибудь придумает название получше :)

using System;
using System.Collections.Generic;
using System.Text;

public static class Extensions
{
    public static string JoinStrings<T>(this IEnumerable<T> source, 
                                        Func<T, string> projection, string separator)
    {
        StringBuilder builder = new StringBuilder();
        bool first = true;
        foreach (T element in source)
        {
            if (first)
            {
                first = false;
            }
            else
            {
                builder.Append(separator);
            }
            builder.Append(projection(element));
        }
        return builder.ToString();
    }

    public static string JoinStrings<T>(this IEnumerable<T> source, string separator)
    {
        return JoinStrings(source, t => t.ToString(), separator);
    }
}

class Test
{

    public static void Main()
    {
        int[] x = {1, 2, 3, 4, 5, 10, 11};

        Console.WriteLine(x.JoinStrings(";"));
        Console.WriteLine(x.JoinStrings(i => i.ToString("X"), ","));
    }
}

Хорошее решение! Однако вам не нужен параметр проекции, вы можете просто написать x.Select (i => i.ToString ("X")). JoinStrings (";"), что более идиоматично.

JacquesB 28.09.2008 22:45

Да, я потом думал об этом. Иногда приятно иметь возможность указать все за один раз, но определенно более элегантно разделить операции :)

Jon Skeet 28.09.2008 22:52

Я согласен с лямбда-выражением для удобства чтения и поддержки, но это не всегда будет лучшим вариантом. Обратной стороной использования обоих подходов IEnumerable / ToArray и StringBuilder является то, что они должны динамически увеличивать список, будь то элементы или символы, поскольку они не знают, сколько места потребуется для конечной строки.

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

int[] number = new int[] { 1, 2, 3, 4, 5 };
string[] strings = new string[number.Length];
for (int i = 0; i < number.Length; i++)
  strings[i] = number[i].ToString();
string result = string.Join(",", strings);

Ты можешь сделать

ints.ToString(",")
ints.ToString("|")
ints.ToString(":")

Проверить

Разделитель ToString с разделителями для массива, списка, словаря, универсального IEnumerable

Для этого требуется метод расширения, определенный на связанной странице, это может быть яснее

StocksR 15.07.2009 14:32

Хотя OP указывал .NET 3.5, люди, желающие сделать это в .NET 2.0 с C# 2, могут сделать это:

string.Join(",", Array.ConvertAll<int, String>(ints, Convert.ToString));

Я обнаружил, что есть ряд других случаев, когда использование функций Convert.xxx является более изящной альтернативой лямбда-выражению, хотя в C# 3 лямбда-функция может помочь в определении типа.

Вот довольно компактная версия C# 3, которая работает с .NET 2.0:

string.Join(",", Array.ConvertAll(ints, item => item.ToString()))

ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);

Я тоже подумал, что есть способ попроще. Не знаю о производительности, у кого-нибудь есть (теоретические) идеи?

Это решение даст вам «1,2,3,4,5».

Sarin 05.12.2010 11:03

Спасибо, я добавил Substring(1), чтобы исправить это (это было по памяти).

void 08.12.2010 19:15

Вопрос в том, чтобы «проще всего преобразовать их в одну строку, в которой числа разделены символом».

Самый простой способ:

int[] numbers = new int[] { 2,3,6,7 };
string number_string = string.Join(",", numbers);
// do whatever you want with your exciting new number string

Обновлено: это работает только в .NET 4.0+, я пропустил требование .NET 3.5, когда впервые прочитал вопрос.

Это недопустимо как строка. Метод Join принимает только массив строк. Посмотрите здесь msdn.microsoft.com/en-us/library/tk0xe5h0.aspx

ppolyzos 05.12.2011 18:17

Это перегруженный метод: msdn.microsoft.com/en-us/library/dd988350 Я просто скопировал написанный мной код в новое консольное приложение, добавил Console.WriteLine и получил результат: 2,3,6,7

WebMasterP 28.08.2012 05:26

Я думаю, что это доступно только в .net 4

Govind Malviya 27.10.2012 13:10

Требуется массив объектов (или массив строк), а не массив int. Выдает ошибку "вызов неоднозначен".

LarryBud 30.04.2015 17:19

В .NET 4.0 соединение строк имеет перегрузку для params object[], поэтому это очень просто:

int[] ids = new int[] { 1, 2, 3 };
string.Join(",", ids);

пример

int[] ids = new int[] { 1, 2, 3 };
System.Data.Common.DbCommand cmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM some_table WHERE id_column IN (@bla)");
cmd.CommandText = cmd.CommandText.Replace("@bla",  string.Join(",", ids));

В .NET 2.0 это немного сложнее, поскольку такой перегрузки нет. Итак, вам нужен собственный общий метод:

public static string JoinArray<T>(string separator, T[] inputTypeArray)
{
    string strRetValue = null;
    System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();

    for (int i = 0; i < inputTypeArray.Length; ++i)
    {
        string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture);

        if (!string.IsNullOrEmpty(str))
        { 
            // SQL-Escape
            // if (typeof(T) == typeof(string))
            //    str = str.Replace("'", "''");

            ls.Add(str);
        } // End if (!string.IsNullOrEmpty(str))

    } // Next i 

    strRetValue= string.Join(separator, ls.ToArray());
    ls.Clear();
    ls = null;

    return strRetValue;
}

В .NET 3.5 вы можете использовать методы расширения:

public static class ArrayEx
{

    public static string JoinArray<T>(this T[] inputTypeArray, string separator)
    {
        string strRetValue = null;
        System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();

        for (int i = 0; i < inputTypeArray.Length; ++i)
        {
            string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture);

            if (!string.IsNullOrEmpty(str))
            { 
                // SQL-Escape
                // if (typeof(T) == typeof(string))
                //    str = str.Replace("'", "''");

                ls.Add(str);
            } // End if (!string.IsNullOrEmpty(str))

        } // Next i 

        strRetValue= string.Join(separator, ls.ToArray());
        ls.Clear();
        ls = null;

        return strRetValue;
    }

}

Таким образом, вы можете использовать метод расширения JoinArray.

int[] ids = new int[] { 1, 2, 3 };
string strIdList = ids.JoinArray(",");

Вы также можете использовать этот метод расширения в .NET 2.0, если вы добавите ExtensionAttribute в свой код:

// you need this once (only), and it must be in this namespace
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
    public sealed class ExtensionAttribute : Attribute {}
}

забудьте о .net 3.5 и используйте следующий код в ядре .net

var result = string.Join(",", ints);

Другие вопросы по теме