У меня есть следующие
data.AppendFormat("{0},",dataToAppend);
Проблема в том, что я использую его в цикле, и там будет пробная запятая. Как лучше всего убрать запятую в конце?
Должен ли я преобразовать данные в строку или ее подстроку?
c#
stringbuilder
Уэсли Скин
источник
источник
string.Join(",", yourCollection)
? Изменить: добавлено в качестве ответа.Ответы:
Самый простой и эффективный способ - выполнить эту команду:
делая это, вы перемещаете указатель (т.е. последний индекс) на один символ назад, но не меняете изменчивость объекта. На самом деле, очистку также
StringBuilder
лучше всего выполнить с помощьюLength
(но на самом делеClear()
вместо этого используйте метод для ясности, потому что так выглядит его реализация):data.Length = 0;
опять же, потому что это не меняет таблицу распределения. Думайте об этом как о том, что я не хочу больше узнавать эти байты. Теперь, даже при звонке
ToString()
, он не узнает ничего, кроме своегоLength
, ну, не может. Это изменяемый объект, который выделяет больше места, чем вы ему предоставляете, он просто построен таким образом.источник
data.Length = 0;
: именно это иStringBuilder.Clear
работает, поэтомуStringBuilder.Clear
для ясности намерений лучше использовать .Clear()
делает, но забавная вещь. Это первая строка изClear()
метода. Но знаете ли вы, что интерфейс на самом деле выдает файлreturn this;
. Вот что меня убивает. УстанавливаяLength = 0
изменения, ссылка у вас уже есть, зачем возвращать самому?Append
тоже возвращается.Просто используйте
string.Join(",", yourCollection)
Таким образом, вам не понадобится
StringBuilder
цикл и.Длинное добавление об async case. По состоянию на 2019 год нередки случаи, когда данные поступают асинхронно.
Если ваши данные находятся в асинхронной коллекции,
string.Join
перегрузки не происходитIAsyncEnumerable<T>
. Но его легко создать вручную, взломав код изstring.Join
:public static class StringEx { public static async Task<string> JoinAsync<T>(string separator, IAsyncEnumerable<T> seq) { if (seq == null) throw new ArgumentNullException(nameof(seq)); await using (var en = seq.GetAsyncEnumerator()) { if (!await en.MoveNextAsync()) return string.Empty; string firstString = en.Current?.ToString(); if (!await en.MoveNextAsync()) return firstString ?? string.Empty; // Null separator and values are handled by the StringBuilder var sb = new StringBuilder(256); sb.Append(firstString); do { var currentValue = en.Current; sb.Append(separator); if (currentValue != null) sb.Append(currentValue); } while (await en.MoveNextAsync()); return sb.ToString(); } } }
Если данные поступают асинхронно, но интерфейс
IAsyncEnumerable<T>
не поддерживается (например, упомянутый в комментарияхSqlDataReader
), относительно легко обернуть данные вIAsyncEnumerable<T>
:async IAsyncEnumerable<(object first, object second, object product)> ExtractData( SqlDataReader reader) { while (await reader.ReadAsync()) yield return (reader[0], reader[1], reader[2]); }
и используйте это:
Task<string> Stringify(SqlDataReader reader) => StringEx.JoinAsync( ", ", ExtractData(reader).Select(x => $"{x.first} * {x.second} = {x.product}"));
Для использования
Select
вам необходимо использовать пакет nugetSystem.Interactive.Async
. Здесь вы можете найти компилируемый пример.источник
string.Join(",", yourCollection)
все еще есть,
в конце. так что приведенное выше iestring.Join(",", yourCollection)
неэффективно и не удаляет его самостоятельно.Используйте следующее после цикла.
.TrimEnd(',')
или просто измените на
string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)
источник
string.Join(",", input)
Как насчет этого..
string str = "The quick brown fox jumps over the lazy dog,"; StringBuilder sb = new StringBuilder(str); sb.Remove(str.Length - 1, 1);
источник
Я предпочитаю манипулировать длиной конструктора строк:
data.Length = data.Length - 1;
источник
data.Length--
или--data.Length
?--
или++
вы можете использоватьdata.Length -= 1
, или этот ответ тоже будет работать.Я рекомендую вам изменить алгоритм цикла:
источник
Вы должны использовать этот
string.Join
метод, чтобы превратить коллекцию элементов в строку, разделенную запятыми. Это обеспечит отсутствие начальной или конечной запятой, а также обеспечит эффективное построение строки (без ненужных промежуточных строк).источник
Да, преобразовать его в строку после завершения цикла:
String str = data.ToString().TrimEnd(',');
источник
У вас есть два варианта. Во-первых, очень простой
Remove
метод использования, он весьма эффективен. Второй способ - использоватьToString
с начальным и конечным индексами ( документация MSDN )источник
Похожий ТАК вопрос здесь.
Мне понравилось использование метода расширения StringBuilder.
RemoveLast метод
источник
Самый простой способ - использовать метод Join ():
public static void Trail() { var list = new List<string> { "lala", "lulu", "lele" }; var data = string.Join(",", list); }
Если вам действительно нужен StringBuilder, обрежьте конечную запятую после цикла:
data.ToString().TrimEnd(',');
источник
data.ToString().TrimEnd(',');
неэффективноПопался!!
Большинство ответов в этой теме не будут работать, если вы воспользуетесь
AppendLine
следующим образом:var builder = new StringBuilder(); builder.AppendLine("One,"); builder.Length--; // Won't work Console.Write(builder.ToString()); builder = new StringBuilder(); builder.AppendLine("One,"); builder.Length += -1; // Won't work Console.Write(builder.ToString()); builder = new StringBuilder(); builder.AppendLine("One,"); Console.Write(builder.TrimEnd(',')); // Won't work
Возьми меня
ЗАЧЕМ??? @ (& ** (& @ !!
Проблема проста, но мне потребовалось время, чтобы разобраться в ней: потому что в конце есть еще 2 невидимых символа
CR
иLF
(возврат каретки и перевод строки). Следовательно, нужно убрать 3 последних символа:var builder = new StringBuilder(); builder.AppendLine("One,"); builder.Length -= 3; // This will work Console.WriteLine(builder.ToString());
В заключении
Используйте
Length--
или,Length -= 1
если последний вызванный вами метод былAppend
. Используйте,Length =- 3
если вы вызывали последний методAppendLine
.источник