ฉันมีดังต่อไปนี้
data.AppendFormat("{0},",dataToAppend);
ปัญหาของเรื่องนี้คือฉันใช้มันวนซ้ำและจะมีลูกน้ำทดลอง วิธีที่ดีที่สุดในการลบเครื่องหมายจุลภาคต่อท้ายคืออะไร?
ฉันต้องเปลี่ยนข้อมูลเป็นสตริงที่สตริงย่อยหรือไม่
ฉันมีดังต่อไปนี้
data.AppendFormat("{0},",dataToAppend);
ปัญหาของเรื่องนี้คือฉันใช้มันวนซ้ำและจะมีลูกน้ำทดลอง วิธีที่ดีที่สุดในการลบเครื่องหมายจุลภาคต่อท้ายคืออะไร?
ฉันต้องเปลี่ยนข้อมูลเป็นสตริงที่สตริงย่อยหรือไม่
คำตอบ:
วิธีที่ง่ายและมีประสิทธิภาพที่สุดคือดำเนินการคำสั่งนี้:
data.Length--;
โดยการทำเช่นนี้คุณจะย้ายตัวชี้ (เช่นดัชนีสุดท้าย) กลับหนึ่งอักขระ แต่คุณจะไม่เปลี่ยนความไม่แน่นอนของวัตถุ ในความเป็นจริงการล้าง a 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 ในปี 2019 ไม่ใช่การตั้งค่าที่หายากเมื่อข้อมูลมาแบบอะซิงโครนัส
ในกรณีที่ข้อมูลของคุณอยู่ในคอลเลกชัน async ไม่มีการซักเกินพิกัด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
nuget ที่นี่คุณสามารถหาตัวอย่างที่ compilableSystem.Interactive.Async
string.Join(",", yourCollection)
ยังคงมี,
ในตอนท้าย ดังนั้นกล่าวstring.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 )
วิธีที่ง่ายที่สุดคือใช้เมธอด 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
(Carriage Return และ Line Feed) ดังนั้นคุณต้องลบ 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
string.Join(",", yourCollection)
เหรอ? แก้ไข: เพิ่มเป็นคำตอบ