IEnumerable to string [дубликат]



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




  • Лучший способ конвертировать IEnumerable в строку?

    6 ответов




Я никогда не натыкался на это раньше, но теперь я удивлен, что не могу найти действительно простой способ конвертировать 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());
701   6  

6 ответов:

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

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

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

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


вот некоторые тесты, которые я взял на машине dev, и это выглядит правильно.

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

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

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

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

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 итераций "новой строки"заняло 869ms.

1000000 итераций "StringBuilder" взял 748ms.

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

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

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

string.Concat(myEnumerable);

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

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
  • итерации = 1000000

Input

  • ((IEnumerable<char>)RandomString(STRLEN)).Reverse()

результаты

  • Concat: 1x
  • новый: 3x
  • StringBuilder: 3x

Input

  • ((IEnumerable<char>)RandomString(STRLEN)).Take((int)ITERATIONS/2)

результаты

  • Concat: 1x
  • новый: 7x
  • StringBuilder: 7x

Input

  • ((IEnumerable<char>)RandomString(STRLEN))(это просто сброс)

результаты

  • Конкат: 0 мс
  • Новый: 2000 МС
  • StringBuilder: 2000 МС
  • подавленный: 0 мс

Я запустил это на Intel i5 760 targeting .NET Framework 3.5.

другая возможность-использование

string.Join("", myEnumerable);

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

вот более краткий вариант ответа 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();
}

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

Comments

    Ничего не найдено.