Я исхожу из фона С#, где System.String
неизменен, а конкатенация строк относительно дорога (поскольку для этого требуется перераспределить строку), мы знаем, что вместо этого используется тип StringBuilder
, поскольку он предопределяет больший буфер, где одиночные символы (Char
, 16-битный тип значения), а короткие строки могут быть объединены дешево без дополнительного распределения.
Я переношу некоторый код С# в Swift, который читает из битового массива ([Bool]
) в индексах под октета с длиной символов менее 8 бит (это очень пространственный формат файла).
Мой код С# делает что-то вроде этого:
StringBuilder sb = new StringBuilder( expectedCharacterCount );
int idxInBits = 0;
Boolean[] bits = ...;
for(int i = 0; i < someLength; i++) {
Char c = ReadNextCharacter( ref idxInBits, 6 ); // each character is 6 bits in this example
sb.Append( c );
}
В Swift я предполагаю, что NSMutableString
является эквивалентом .NET StringBuilder
, и я нашел этот QA о добавлении отдельных символов (Как добавить символ в строку в Swift?), поэтому в Swift у меня есть следующее:
var buffer: NSMutableString
for i in 0..<charCount {
let charValue: Character = readNextCharacter( ... )
buffer.AppendWithFormat("%c", charValue)
}
return String(buffer)
Но я не знаю, почему он сначала проходит через строку формата, что кажется неэффективным (переписывая строку формата на каждой итерации), и когда мой код работает на устройствах iOS, я хочу быть очень консервативным с моей программой Использование процессора и памяти.
Как я писал это, я узнал, что мой код действительно должен использовать UnicodeScalar
вместо Character
, проблема NSMutableString
не позволяет вам добавить значение UnicodeScalar
, вы должны использовать Swift own mutable String
, поэтому теперь мой код выглядит следующим образом:
var buffer: String
for i in 0..<charCount {
let x: UnicodeScalar = readNextCharacter( ... )
buffer.append(x)
}
return buffer
Я думал, что String
является неизменным, но я заметил, что его метод append
возвращает Void
.
Мне все еще кажется неудобным делать это, потому что я не знаю, как тип Swift String
реализуется внутренне, и я не вижу, как я могу перераспределить большой буфер, чтобы избежать перераспределения (если Swift String
использует растущее алгоритм).