Самый эффективный способ соединения строк - PullRequest
7 голосов
/ 02 мая 2011

Мне нужно объединить множество строк и поставить запятую между ними. У меня есть список строк

"123123123213"
"1232113213213"
"123213123"

и я хочу получить

"123123123213,1232113213213,123213123"

Мне было интересно, как лучше всего этого достичь.

Я мог бы сделать это так:

private List<string> stringList = new List<string> { 
    // a lot of strings in here
    "1234567890", "34343434", "4343434" }; 

string outcome = string.Join(",", stringList.ToArray());

Или, может быть:

StringBuilder builder = new StringBuilder();
stringList.ForEach(val => {
    builder.Append(val);
    builder.Append(",");
});

string outcome = builder.ToString();

Какой путь лучше? Знаете ли вы лучшие способы объединения строк?

Ответы [ 11 ]

6 голосов
/ 02 мая 2011

Как сказал @ Ekkehard , используйте строку . Присоединяйтесь .

Однако вам не нужен ToArray(), поскольку string.Join имеет перегрузку для IEnumerable<string>.

List<string> stringList = new List<string> 
    { "1234567890", "34343434", "4343434" }; 

string outcome = string.Join(",", stringList);

EDIT

Как сказал @ Kobi , это будет работать только в C # 4.0.В 3.5 я бы сделал.

var s = new StringBuilder(stringList.Count * 8);
foreach (var item in stringList)
{
   s.Append(item);
   s.Append(',');
}
s.Length -= 1;
string outcome = stringList.ToList();
5 голосов
/ 02 мая 2011

Вы должны использовать string.Join(), потому что:

a) он гораздо более читабелен, удобен в обслуживании и прост для глаз.

b) он уже использует StringBuilder внутри, поэтомуочень эффективно (вы можете подтвердить себя, используя Reflector).

Редактировать:

string.Join() использует StringBuilder для общего случая ввода IEnumerable<T>.С другой стороны, если у вас уже есть массив, он использует магию вуду (включая FastAllocateString() и UnSafeCharBuffer), чтобы быть еще быстрее.

1 голос
/ 02 мая 2011

Ваше второе решение добавляет дополнительные , в конце.Взгляните на запись в блоге Эрика Липперта

Я бы порекомендовал исправить ваше второе решение.StringBuilder будет определенно быстрее, поскольку вы не будете копировать содержимое списка в новый массив.

StringBuilder builder = new StringBuilder();
string separator = "";
stringList.ForEach(
    val =>
    {
        builder.Append(separator).Append(val);
        separator = ",";
    });
string outcome = builder.ToString();
1 голос
/ 02 мая 2011

На этой странице есть тест, который, кажется, показывает, что string.Join работает лучше, чем StringBuilder для небольшого массива за много итераций. Вы, вероятно, должны также ориентироваться для больших массивов. Когда я публикую это, я вижу, что BrokenGlass ответил, что StringBuilder используется внутри string.Join, поэтому вы можете ожидать, что это будет быстрее, я думаю.

1 голос
/ 02 мая 2011

Используйте Join, потому что он не добавляет завершающий ",".

0 голосов
/ 02 мая 2011

Если кто-то хочет быть крутым и работать на Тяжелое топливо , используйте Агрегат

List<string> stringList = new List<string> { "1234567890", "34343434", "4343434" };

Console.WriteLine( stringList.Aggregate( ( current, next ) => string.Format( "{0}, {1}", current, next ) ) );

// Outputs:   1234567890, 34343434, 4343434
0 голосов
/ 02 мая 2011

Тестовый код:

public static void Performance(Action fn)
{
    var timer = new Stopwatch();
    timer.Start();

    for (var i = 0; i < 10000000; ++i)
    {
        fn();
    }

    timer.Stop();

    Console.WriteLine("{0} Time: {1}ms ({2})", fn.ToString(), timer.ElapsedMilliseconds, timer.ElapsedTicks);
}

static void Main(string[] args)
{
    var stringList = new List<string>() {
        "123123123213",
        "1232113213213",
        "123213123"
    };

    string outcome = String.Empty;
    Performance(() =>
    {
        outcome = string.Join(",", stringList);
    });

    Console.WriteLine(outcome);

    Performance(() =>
    {
        StringBuilder builder = new StringBuilder();
        stringList.ForEach
            (
                val =>
                {
                    builder.Append(val);
                    builder.Append(",");
                }
            );
        outcome = builder.ToString();
        outcome = outcome.Substring(0, outcome.Length - 1);
    });

    Console.WriteLine(outcome);

    Console.ReadKey();

}

Результат 1. String.Join - 2. StringBuilder + SubString. ####ms (ticks)

result

В этом случае String.Join быстрее, но если вы в порядке с трейлингом ,, тогда

string builder

StringBuilder немного быстрее (с трейлингом ,).

0 голосов
/ 02 мая 2011

String.Join - самый быстрый, если у вас есть фиксированное количество строк для присоединения. Более глубокая причина заключается в том, что String.Join выполняет цикл по массиву и выделяет последний строковый буфер с правильным размером, поскольку он при первом проходе добавляет длину строки всех строк вместе. Вы можете получить аналогичные результаты, играя с StringBuilder и его возможностями. Золотое правило заключается в том, чтобы сэкономить выделение памяти за счет зацикливания массива два раза. Какой подход быстрее, зависит от того, сколько элементов в вашем списке и насколько велика будет строка результата.

С уважением, Алоис Краус

0 голосов
/ 02 мая 2011

Согласно следующему тесту, Присоединение в 3 раза быстрее на больших массивах:

Файл Text.txt содержит значение "aaaaaaaaaaaaaaaaaaa" в 38400 строках:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      var strings = File.ReadAllLines("Text.txt");

      Stopwatch sw;

      StringBuilder sb = new StringBuilder();

      sw = Stopwatch.StartNew();
      for (int i = 0; i < strings.Length; i++)
      {
        sb.AppendLine(strings[i]);
      }
      sw.Stop();
      TimeSpan sbTime = sw.Elapsed;

      sw = Stopwatch.StartNew();
     var output = string.Join(",", strings);
     sw.Stop();

     TimeSpan joinTime = sw.Elapsed;   

    }
  }
}

Выход:

00:00:00.0098754
00:00:00.0032922
0 голосов
/ 02 мая 2011

Эта временная реализация, которую я пробовал с StrignBuilder, работает быстрее, чем String.Join.Более того String.Join - HOG ПАМЯТИ.Я пытался с 20000000 строк и String.Join всегда дает OutOfMemory, когда моя реализация заканчивается.На вашей машине может быть даже меньше строк, если у вас меньше 8 ГБ памяти.Прокомментируйте одну из реализаций для тестирования.Это верно, если вы не используете фиксированный массив string [].String.Join там хорош.

   public static void Main(string[] Args)
    {
        Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

          List<string> strings = new List<string>() {};
        for (double d = 0; d < 8000000; d++) {
            strings.Add(d.ToString());
        }

        TimeSpan upTime;
        TimeSpan newupTime;
        using (var pc = new PerformanceCounter("System", "System Up Time"))
        {
            StringBuilder sb = new StringBuilder(strings.Count);
            int i;

            pc.NextValue();    //The first call returns 0, so call this twice
            upTime = TimeSpan.FromSeconds(pc.NextValue());

            for (i = 0; i < strings.Count - 1; i++)
            {
                sb.Append(strings[i]);
                sb.Append(",");
            }
            sb.Append(strings[i]);

            newupTime = TimeSpan.FromSeconds(pc.NextValue());
            sb = null;
            Console.WriteLine("SB " + (newupTime - upTime).TotalMilliseconds);
        }

        using (var pc = new PerformanceCounter("System", "System Up Time"))
        {

            pc.NextValue();
            upTime = TimeSpan.FromSeconds(pc.NextValue());

            string s = string.Join(",", strings);

            newupTime = TimeSpan.FromSeconds(pc.NextValue());
            Console.WriteLine("JOIN " + (newupTime - upTime).TotalMilliseconds);
        }


    }
SB 406
JOIN 484
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...