IEnumerable & л; символ > в строку [дублировать]

    

На этот вопрос уже есть ответ здесь:

    

Я никогда раньше не сталкивался с этим, но сейчас удивляюсь, что не могу найти действительно простой способ конвертировать IEnumerable<char> для string.

Лучший способ, о котором я могу думать, это string str = new string(myEnumerable.ToArray());, но мне кажется, что это создаст новый char[], а затем создайте новый string из этого, который кажется дорогим.

Я бы подумал, что это будет обычная функциональность, встроенная где-то в .NET Framework. Есть ли более простой способ сделать это?

Для интересующихся причина, по которой я хотел бы использовать это, заключается в использовании LINQ для фильтрации строк:

string allowedString = new string(inputString.Where(c => allowedChars.Contains(c)).ToArray());
112 голосов | спросил Connell 25 J000000Wednesday12 2012, 20:17:51

6 ответов


0

Вы можете использовать String.Concat() .

var allowedString = String.Concat(
    inputString.Where(c => allowedChars.Contains(c))
);

Предостережение . Этот подход может повлиять на производительность. String.Concat не содержит специальных наборов символов, поэтому он работает так, как если бы каждый символ был преобразован в строку, а затем объединен, как упомянуто в документации ( и это действительно так ). Конечно, это дает вам встроенный способ выполнить эту задачу, но это может быть сделано лучше.

Я не думаю, что в рамках фреймворка есть какие-либо реализации, которые будут иметь особый случай char, поэтому вам придется его реализовать. Простой цикл добавления символов в построитель строк достаточно прост для создания.


Вот некоторые тесты, которые я взял на машине разработчика, и она выглядит примерно так.

1000000 итераций для последовательности из 300 символов в 32-разрядной сборке выпуска:

ToArrayString: 00: 00: 03.1695463
Concat: 00: 00: 07.2518054
StringBuilderChars: 00: 00: 03.1335455
StringBuilderStrings: 00: 00: 06.4618266
static readonly IEnumerable<char> seq = Enumerable.Repeat('a', 300);

static string ToArrayString(IEnumerable<char> charSequence)
{
    return new String(charSequence.ToArray());
}

static string Concat(IEnumerable<char> charSequence)
{
    return String.Concat(charSequence);
}

static string StringBuilderChars(IEnumerable<char> charSequence)
{
    var sb = new StringBuilder();
    foreach (var c in charSequence)
    {
        sb.Append(c);
    }
    return sb.ToString();
}

static string StringBuilderStrings(IEnumerable<char> charSequence)
{
    var sb = new StringBuilder();
    foreach (var c in charSequence)
    {
        sb.Append(c.ToString());
    }
    return sb.ToString();
}
ответил Jeff Mercado 25 J000000Wednesday12 2012, 20:19:34
0

Отредактировано для выпуска .Net Core 2.1

Повторяя тест для выпуска .Net Core 2.1, я получаю такие результаты

  

1000000 итераций "Concat" заняли 842 мс.

     

1000000 итераций "новой строки" заняло 1009 мс.

     

1000000 итераций sb заняло 902 мс.

Короче говоря, если вы используете .Net Core 2.1 или новее, Concat - король.

См. MS. сообщение в блоге для получения дополнительной информации.


Я сделал это предметом другой вопрос , но все больше и больше становится прямым ответом на этот вопрос.

Я провел несколько тестов производительности 3 простых способов преобразования IEnumerable<char> в string, эти методы

  

новая строка

return new string(charSequence.ToArray());
  

Concat

return string.Concat(charSequence)
  

StringBuilder

var sb = new StringBuilder();
foreach (var c in charSequence)
{
    sb.Append(c);
}

return sb.ToString();

В моем тестировании это подробно описано в связанный вопрос , для 1000000 итераций "Some reasonably small test data" Я получаю такие результаты,

  

1000000 итераций "Concat" заняли 1597 мс.

     

1000000 итераций «новой строки» заняли 869 мс.

     

1000000 итераций "StringBuilder" заняли 748 мс.

Это говорит о том, что нет веских причин использовать string.Concat для этой задачи. Если вы хотите простоты, используйте подход новая строка , а если хотите производительности, используйте StringBuilder .

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

ответил Jodrell 11 FebruaryEurope/MoscowbMon, 11 Feb 2013 16:37:28 +0400000000pmMon, 11 Feb 2013 16:37:28 +040013 2013, 16:37:28
0

Начиная с .NET 4, многие строковые методы принимают IEnumerable в качестве аргументов.

string.Concat(myEnumerable);
ответил MikeP 25 J000000Wednesday12 2012, 20:19:38
0

Мои данные противоречат результатам, опубликованным Джодреллом. Сначала посмотрим на методы расширения, которые я использую:

public static string AsStringConcat(this IEnumerable<char> characters)
{        
    return String.Concat(characters);
}

public static string AsStringNew(this IEnumerable<char> characters)
{
    return new String(characters.ToArray());
}

public static string AsStringSb(this IEnumerable<char> characters)
{
    StringBuilder sb = new StringBuilder();
    foreach (char c in characters)
    {
        sb.Append(c);
    }
    return sb.ToString();
}

Мои результаты

С

  • STRLEN = 31
  • ITERATIONS = 1000000

Ввод

    ((IEnumerable<char>)RandomString(STRLEN)).Reverse() литий>

Результаты

  • Concat: 1x
  • Новое: 3x
  • StringBuilder: 3x

Ввод

    ((IEnumerable<char>)RandomString(STRLEN)).Take((int)ITERATIONS/2) литий>

Результаты

  • Concat: 1x
  • Новое: 7x
  • StringBuilder: 7x

Ввод

  • ((IEnumerable<char>)RandomString(STRLEN)) (это просто уныние)

Результаты

  • Concat: 0 мс
  • Новое: 2000 мс
  • StringBuilder: 2000 мс
  • Downcast: 0 мс

Я запустил это на Intel i5 760 с таргетингом на .NET Framework 3.5.

ответил hBGl 4 J000000Thursday13 2013, 02:07:07
0

Еще одна возможность - использовать

string.Join("", myEnumerable);

Я не измерял производительность.

ответил nitrogenycs 21 PM00000050000002231 2014, 17:21:22
0

Вот более краткая версия ответа StringBuilder:

return charSequence.Aggregate(new StringBuilder(), (seed, c) => seed.Append(c)).ToString();

Я рассчитал это, используя те же тесты, которые использовал Джефф Меркадо, и это было на 1 секунду медленнее на 1 000 000 итераций в одной и той же последовательности из 300 символов (сборка 32-разрядной версии), чем более явное:

static string StringBuilderChars(IEnumerable<char> charSequence)
{
    var sb = new StringBuilder();
    foreach (var c in charSequence)
    {
        sb.Append(c);
    }
    return sb.ToString();
}

Так что, если вы поклонник аккумуляторов, то здесь вы идете.

ответил Adam Smith 24 +04002014-10-24T08:31:14+04:00312014bEurope/MoscowFri, 24 Oct 2014 08:31:14 +0400 2014, 08:31:14

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132