การสร้างรายการที่คั่นด้วยเครื่องหมายจุลภาคจาก IList <string> หรือ IEnumerable <string>


848

วิธีที่สะอาดที่สุดในการสร้างรายการสตริงที่คั่นด้วยเครื่องหมายจุลภาคจากIList<string>หรือIEnumerable<string>คืออะไร?

String.Join(...)ทำงานบนstring[]ดังนั้นสามารถยุ่งยากในการทำงานกับเมื่อชนิดเช่นIList<string>หรือIEnumerable<string>ไม่สามารถแปลงเป็นอาร์เรย์สตริงได้อย่างง่ายดาย


5
โอ้ ... อ๊ะ ฉันพลาดนอกเหนือจากวิธีขยาย toArray ใน 3.5:public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
แดเนียล Fortunov

1
หากคุณมาที่คำถามนี้เพื่อค้นหาวิธีการเขียน CSV คุณควรจำไว้ว่าการใส่เครื่องหมายจุลภาคระหว่างรายการไม่เพียงพอและจะทำให้เกิดความล้มเหลวในกรณีของคำพูดและเครื่องหมายจุลภาคในแหล่งข้อมูล
ผู้

คำตอบ:


1446

. NET 4+

IList<string> strings = new List<string>{"1","2","testing"};
string joined = string.Join(",", strings);

รายละเอียด & Pre. Net 4.0 Solutions

IEnumerable<string>สามารถแปลงเป็นอาร์เรย์สตริงมากได้อย่างง่ายดายด้วย LINQ (NET 3.5):

IEnumerable<string> strings = ...;
string[] array = strings.ToArray();

มันง่ายพอที่จะเขียนวิธีช่วยเทียบเท่าหากคุณต้องการ:

public static T[] ToArray(IEnumerable<T> source)
{
    return new List<T>(source).ToArray();
}

จากนั้นเรียกมันว่าสิ่งนี้:

IEnumerable<string> strings = ...;
string[] array = Helpers.ToArray(strings);

string.Joinจากนั้นคุณสามารถโทรหา แน่นอนคุณไม่ต้องใช้วิธีช่วย:

// C# 3 and .NET 3.5 way:
string joined = string.Join(",", strings.ToArray());
// C# 2 and .NET 2.0 way:
string joined = string.Join(",", new List<string>(strings).ToArray());

หลังเป็นบิตของคำว่า :)

นี่คือแนวโน้มที่จะเป็นวิธีที่ง่ายที่สุดที่จะทำมันและค่อนข้าง performant เป็นอย่างดี - มีคำถามอื่น ๆ เกี่ยวกับสิ่งที่ผลการดำเนินงานเป็นเหมือนรวมทั้ง ( แต่ไม่ จำกัด เฉพาะ) คนนี้

ในฐานะของ. NET 4.0 มีการโอเวอร์โหลดมากขึ้นstring.Joinดังนั้นคุณสามารถเขียนได้จริง:

string joined = string.Join(",", strings);

ง่ายกว่า :)


วิธีการช่วยเหลือเกี่ยวข้องกับการสร้างสองรายการที่ไม่จำเป็น นี่เป็นวิธีที่ดีที่สุดในการแก้ปัญหาหรือไม่ ทำไมไม่เชื่อมต่อตัวคุณเองด้วยการวนรอบ foreach?
Eric

4
วิธีการช่วยเหลือสร้างเพียงหนึ่งรายการและหนึ่งอาร์เรย์ ประเด็นก็คือผลลัพธ์จะต้องเป็นอาร์เรย์ไม่ใช่รายการ ... และคุณต้องรู้ขนาดของอาร์เรย์ก่อนที่จะเริ่ม แนวปฏิบัติที่ดีที่สุดกล่าวว่าคุณไม่ควรระบุแหล่งที่มามากกว่าหนึ่งครั้งใน LINQ เว้นแต่คุณจะต้องทำ - อาจเป็นการทำสิ่งที่น่ารังเกียจทุกประเภท ดังนั้นคุณเหลือที่จะอ่านเป็นบัฟเฟอร์และปรับขนาดตามที่คุณไป - ซึ่งเป็นสิ่งที่List<T>ทำ ทำไมต้องคิดค้นล้อใหม่
Jon Skeet

9
ไม่ประเด็นคือผลลัพธ์จะต้องเป็นสตริงที่ต่อกัน ไม่จำเป็นต้องสร้างรายการใหม่หรืออาร์เรย์ใหม่เพื่อให้บรรลุเป้าหมายนี้ ความคิดแบบ. NET ประเภทนี้ทำให้ฉันเศร้า
Eric

38
แค่นั้นแหละ. ทุกคำตอบนำไปสู่ ​​Jon Skeet ฉันกำลังจะไปยัง PurchaseBooks = AmazonContainer.Where (p => p.Author == "Jon Skeet") เลือก ();
Zachary Scott

3
@ codeMonkey0110: ToListดีมีจุดในการมีการแสดงออกแบบสอบถามมีหรือไม่มีการเรียก มันปรับให้ใช้งานstring myStr = string.Join(",", foo.Select(a => a.someInt.ToString()))แต่
Jon Skeet

179

FYI เวอร์ชัน. NET 4.0 string.Join()มีโอเวอร์โหลดพิเศษบางอย่างที่ทำงานด้วยIEnumerableแทนที่จะเป็นเพียงอาร์เรย์รวมถึงรุ่นที่สามารถจัดการกับประเภทใดก็ได้T:

public static string Join(string separator, IEnumerable<string> values)
public static string Join<T>(string separator, IEnumerable<T> values)

2
สิ่งนี้จะเรียกเมธอด T.ToString ()
Philippe Lavoie

เพิ่งจะแสดงความคิดเห็นในคำตอบของจอน ขอบคุณที่พูดถึง
Dan Bechard

2
ยังไงก็ตามที่จะทำสิ่งนี้กับคุณสมบัติของวัตถุ? (ตัวอย่าง: IEnumerable <Employee> และวัตถุ Employee มีคุณสมบัติเป็นสตริง. SSN และได้รับรายการที่คั่นด้วยเครื่องหมายจุลภาคของ SSN)
granadaCoder

1
คุณต้องเลือกสตริงก่อนแม้ว่าคุณจะสามารถสร้างวิธีการขยายได้ str = emps.Select(e => e.SSN).Join(",")
Xavier Poinas

65

วิธีที่ง่ายที่สุดที่ฉันสามารถทำได้คือใช้AggregateวิธีLINQ :

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)

20
นั่นไม่เพียงซับซ้อนกว่า (IMO) มากกว่า ToArray + เข้าร่วม แต่ก็ไม่มีประสิทธิภาพ - ด้วยลำดับการป้อนข้อมูลขนาดใหญ่ที่จะเริ่มทำงานได้ไม่ดีมาก
Jon Skeet

35
ถึงกระนั้นมันก็สวยที่สุด
Merritt

2
คุณสามารถเลี้ยงรวมเมล็ด StringBuilder แล้วรวม Func Func<StringBuilder,string,StringBuider>คุณจะกลายเป็น จากนั้นเพียงโทรหาToString()StringBuilder ที่ส่งคืน แน่นอนว่ามันไม่ได้สวยเหมือนกัน :)
Matt Greer

3
นี่เป็นวิธีที่ชัดเจนที่สุดในการทำสิ่งที่คำถามถาม IMHO
Derek Morrison

8
ระวังว่าinput.Countควรมากกว่า 1
ยองแจ

31

ฉันคิดว่าวิธีที่สะอาดที่สุดในการสร้างรายการสตริงที่คั่นด้วยเครื่องหมายจุลภาคนั้นเป็นเพียง:

string.Join<string>(",", stringEnumerable);

นี่คือตัวอย่างเต็มรูปแบบ:

IEnumerable<string> stringEnumerable= new List<string>();
stringList.Add("Comma");
stringList.Add("Separated");

string.Join<string>(",", stringEnumerable);

ไม่จำเป็นต้องสร้างฟังก์ชันผู้ช่วยซึ่งสร้างไว้ใน. NET 4.0 ขึ้นไป


4
โปรดทราบว่าสิ่งนี้สามารถเริ่มต้นได้ด้วย. NET 4 (ตามที่ Xavier ชี้ให้เห็นในคำตอบของเขา)
Derek Morrison

จากมุมมองของ. NET 4 มือใหม่ที่มีประสบการณ์น้อยกว่าหนึ่งเดือนคำตอบนี้เป็นการผสมผสานที่ลงตัวระหว่างความถูกต้องและความรัดกุม
Dexygen

13

เมื่อเปรียบเทียบกับการแสดงผู้ชนะคือ "Loop it, sb.Append และทำการย้อนกลับ" ที่จริง "นับและย้ายด้วยตนเองต่อไป" เป็นสิ่งที่ดีเหมือนกัน (พิจารณา stddev)

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC
  [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
  Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
  Core   : .NET Core 4.6.25009.03, 64bit RyuJIT


                Method |  Job | Runtime |     Mean |     Error |    StdDev |      Min |      Max |   Median | Rank |  Gen 0 | Allocated |
---------------------- |----- |-------- |---------:|----------:|----------:|---------:|---------:|---------:|-----:|-------:|----------:|
            StringJoin |  Clr |     Clr | 28.24 us | 0.4381 us | 0.3659 us | 27.68 us | 29.10 us | 28.21 us |    8 | 4.9969 |   16.3 kB |
 SeparatorSubstitution |  Clr |     Clr | 17.90 us | 0.2900 us | 0.2712 us | 17.55 us | 18.37 us | 17.80 us |    6 | 4.9296 |  16.27 kB |
     SeparatorStepBack |  Clr |     Clr | 16.81 us | 0.1289 us | 0.1206 us | 16.64 us | 17.05 us | 16.81 us |    2 | 4.9459 |  16.27 kB |
            Enumerable |  Clr |     Clr | 17.27 us | 0.0736 us | 0.0615 us | 17.17 us | 17.36 us | 17.29 us |    4 | 4.9377 |  16.27 kB |
            StringJoin | Core |    Core | 27.51 us | 0.5340 us | 0.4995 us | 26.80 us | 28.25 us | 27.51 us |    7 | 5.0296 |  16.26 kB |
 SeparatorSubstitution | Core |    Core | 17.37 us | 0.1664 us | 0.1557 us | 17.15 us | 17.68 us | 17.39 us |    5 | 4.9622 |  16.22 kB |
     SeparatorStepBack | Core |    Core | 15.65 us | 0.1545 us | 0.1290 us | 15.45 us | 15.82 us | 15.66 us |    1 | 4.9622 |  16.22 kB |
            Enumerable | Core |    Core | 17.00 us | 0.0905 us | 0.0654 us | 16.93 us | 17.12 us | 16.98 us |    3 | 4.9622 |  16.22 kB |

รหัส:

public class BenchmarkStringUnion
{
    List<string> testData = new List<string>();
    public BenchmarkStringUnion()
    {
        for(int i=0;i<1000;i++)
        {
            testData.Add(i.ToString());
        }
    }
    [Benchmark]
    public string StringJoin()
    {
        var text = string.Join<string>(",", testData);
        return text;
    }
    [Benchmark]
    public string SeparatorSubstitution()
    {
        var sb = new StringBuilder();
        var separator = String.Empty;
        foreach (var value in testData)
        {
            sb.Append(separator).Append(value);
            separator = ",";
        }
        return sb.ToString();
    }

    [Benchmark]
    public string SeparatorStepBack()
    {
        var sb = new StringBuilder();
        foreach (var item in testData)
            sb.Append(item).Append(',');
        if (sb.Length>=1) 
            sb.Length--;
        return sb.ToString();
    }

    [Benchmark]
    public string Enumerable()
    {
        var sb = new StringBuilder();
        var e = testData.GetEnumerator();
        bool  moveNext = e.MoveNext();
        while (moveNext)
        {
            sb.Append(e.Current);
            moveNext = e.MoveNext();
            if (moveNext) 
                sb.Append(",");
        }
        return sb.ToString();
    }
}

https://github.com/dotnet/BenchmarkDotNetถูกนำมาใช้


11

เนื่องจากฉันมาถึงที่นี่ในขณะที่ค้นหาเพื่อเข้าร่วมในคุณสมบัติเฉพาะของรายการวัตถุ (ไม่ใช่ ToString () ของมัน) นี่เป็นส่วนเพิ่มเติมของคำตอบที่ยอมรับ:

var commaDelimited = string.Join(",", students.Where(i => i.Category == studentCategory)
                                 .Select(i => i.FirstName));

9

ต่อไปนี้เป็นวิธีส่วนขยายอื่น:

    public static string Join(this IEnumerable<string> source, string separator)
    {
        return string.Join(separator, source);
    }

8

มาถึงสายเล็กน้อยเพื่อการสนทนานี้ แต่นี่คือผลงานของฉัน fwiw ฉันต้องIList<Guid> OrderIdsแปลงเป็นสตริง CSV แต่ต่อไปนี้เป็นไฟล์ทั่วไปและทำงานโดยไม่แก้ไขกับประเภทอื่น:

string csv = OrderIds.Aggregate(new StringBuilder(),
             (sb, v) => sb.Append(v).Append(","),
             sb => {if (0 < sb.Length) sb.Length--; return sb.ToString();});

สั้นและหวานใช้ StringBuilder สำหรับการสร้างสตริงใหม่ลดขนาดความยาว StringBuilder ทีละหนึ่งเพื่อลบเครื่องหมายจุลภาคสุดท้ายและส่งกลับสตริง CSV

ฉันได้อัปเดตสิ่งนี้เพื่อใช้หลายรายการAppend()เพื่อเพิ่มสตริง + คอมม่า StringBuilder.AppendFormat()จากความคิดเห็นของเจมส์ผมใช้กระจกสะท้อนแสงจะมีลักษณะที่ ผลัดกันออกมาAppendFormat()ใช้ในการสร้าง StringBuilder สตริงรูปแบบซึ่งจะทำให้มันมีประสิทธิภาพน้อยลงในบริบทนี้มากกว่าเพียงแค่การใช้หลายAppends()'s


Gazumped ขอบคุณ Xavier ฉันไม่ทราบว่ามีการอัพเดตใน. Net4 โครงการที่ฉันกำลังทำอยู่ยังไม่ได้ก้าวกระโดดดังนั้นฉันจะใช้ตัวอย่างคนเดินเท้าตอนนี้ต่อไปในระหว่างนี้
David Clarke

2
สิ่งนี้จะล้มเหลวด้วยแหล่งข้อมูล IEnumerable ศูนย์สินค้า ความยาว - ต้องการการตรวจสอบขอบเขต
James Dunne

ขอบคุณมาก James ในบริบทที่ฉันใช้สิ่งนี้ฉัน "รับประกัน" ให้มี OrderId อย่างน้อยหนึ่งรายการ ฉันได้อัปเดตทั้งตัวอย่างและรหัสของฉันเองเพื่อรวมการตรวจสอบขอบเขต (เพื่อให้แน่ใจ)
David Clarke

@ James ฉันคิดว่าการเรียก sb.Length - การแฮ็คค่อนข้างรุนแรง อย่างมีประสิทธิภาพฉันแค่หลีกเลี่ยงการทดสอบ "if (notdone)" ของคุณจนกว่าจะสิ้นสุดแทนที่จะทำในการทำซ้ำแต่ละครั้ง
David Clarke

1
@ James ประเด็นของฉันคือมักจะมีคำตอบที่ถูกต้องมากกว่าหนึ่งคำถามที่ถามที่นี่และอ้างถึงหนึ่งว่า "แฮ็ค" บอกว่ามันไม่ถูกต้องซึ่งฉันจะโต้แย้ง สำหรับ guids จำนวนน้อยฉันเชื่อมคำตอบของ Daniel ไว้ด้านบนอาจจะเพียงพออย่างสมบูรณ์และแน่นอนยิ่งขึ้น ฉันใช้สิ่งนี้ในที่เดียวในรหัสของฉันและฉันจะใช้เครื่องหมายจุลภาคเป็นตัวคั่นเท่านั้น YAGNI พูดว่าอย่าสร้างสิ่งที่คุณไม่ต้องการ การอบแห้งจะใช้งานได้หากฉันต้องการทำมากกว่าหนึ่งครั้ง ณ จุดที่ฉันจะสร้างวิธีการขยาย HTH
David Clarke

7

บางสิ่งบางอย่างน่าเกลียดเล็กน้อย แต่มันได้ผล:

string divisionsCSV = String.Join(",", ((List<IDivisionView>)divisions).ConvertAll<string>(d => d.DivisionID.ToString("b")).ToArray());

ให้ CSV จากรายการหลังจากที่คุณให้ตัวแปลง (ในกรณีนี้ d => d.DivisionID.ToString ("b"))

การแฮ็ก แต่ใช้ได้ผล - อาจทำเป็นวิธีการเสริมได้ไหม


7

นี่คือวิธีที่ฉันทำโดยใช้วิธีที่ฉันทำได้ในภาษาอื่น:

private string ToStringList<T>(IEnumerable<T> list, string delimiter)
{
  var sb = new StringBuilder();
  string separator = String.Empty;
  foreach (T value in list)
  {
    sb.Append(separator).Append(value);
    separator = delimiter;
  }
  return sb.ToString();
}

7

ความต้องการเฉพาะเมื่อเราควรล้อมรอบด้วย 'โดยอดีต:

        string[] arr = { "jj", "laa", "123" };
        List<string> myList = arr.ToList();

        // 'jj', 'laa', '123'
        Console.WriteLine(string.Join(", ",
            myList.ConvertAll(m =>
                string.Format("'{0}'", m)).ToArray()));

4

เรามีฟังก์ชั่นยูทิลิตี้บางอย่างเช่นนี้:

public static string Join<T>( string delimiter, 
    IEnumerable<T> collection, Func<T, string> convert )
{
    return string.Join( delimiter, 
        collection.Select( convert ).ToArray() );
}

ซึ่งสามารถใช้สำหรับการเข้าร่วมคอลเลกชันจำนวนมากได้อย่างง่ายดาย:

int[] ids = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233};

string csv = StringUtility.Join(",", ids, i => i.ToString() );

โปรดทราบว่าเรามีพารามิเตอร์การรวบรวมไว้ด้านหน้าแลมบ์ดาเนื่องจาก intellisense จะเลือกประเภทคอลเลกชัน

หากคุณมีการแจงนับสตริงสิ่งที่คุณต้องทำคือ ToArray:

string csv = string.Join( ",", myStrings.ToArray() );

2
ฉันมีวิธีขยายที่ไม่เกือบตรงสิ่งเดียวกันมีประโยชน์มาก: stackoverflow.com/questions/696850/...
LukeH

ใช่คุณสามารถเขียนสิ่งนี้เป็นวิธีการขยาย. ToDelimitedString ได้ง่ายพอ ฉันจะไปกับสตริงบรรทัดเดียวของฉันเข้าร่วมหนึ่งมากกว่าการใช้ StringBuilder การตัดแต่งอักขระตัวสุดท้าย
Keith

3

คุณสามารถแปลง IList เป็นอาร์เรย์โดยใช้ ToArray จากนั้นเรียกใช้คำสั่ง string.join บนอาเรย์

Dim strs As New List(Of String)
Dim arr As Array
arr = strs.ToArray

3

สามารถแปลงเป็นอาร์เรย์ได้อย่างง่ายดายโดยใช้ส่วนขยาย Linq ใน. NET 3.5

   var stringArray = stringList.ToArray();

3

คุณสามารถใช้บางอย่างเช่นต่อไปนี้หลังจากที่คุณแปลงเป็นอาร์เรย์โดยใช้วิธีใดวิธีหนึ่งจากรายการอื่น ๆ :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Configuration;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();
            string[] itemList = { "Test1", "Test2", "Test3" };
            commaStr.AddRange(itemList);
            Console.WriteLine(commaStr.ToString()); //Outputs Test1,Test2,Test3
            Console.ReadLine();
        }
    }
}

แก้ไข: นี่เป็นอีกตัวอย่างหนึ่ง


3

ฉันเพิ่งแก้ไขปัญหานี้ก่อนที่จะเกิดขึ้นกับบทความนี้ โซลูชันของฉันมีลักษณะดังนี้:

   private static string GetSeparator<T>(IList<T> list, T item)
   {
       return (list.IndexOf(item) == list.Count - 1) ? "" : ", ";
   }

เรียกว่า:

List<thing> myThings;
string tidyString;

foreach (var thing in myThings)
{
     tidyString += string.format("Thing {0} is a {1}", thing.id, thing.name) + GetSeparator(myThings, thing);
}

ฉันสามารถแสดงได้อย่างง่ายดายเช่นนี้และจะมีประสิทธิภาพมากขึ้น:

string.Join(“,”, myThings.Select(t => string.format(“Thing {0} is a {1}”, t.id, t.name)); 

3

คำตอบของฉันเป็นเหมือนโซลูชันรวมข้างต้น แต่ควรมี call-stack หนักน้อยลงเนื่องจากไม่มีการโทรแบบมอบหมายอย่างชัดเจน:

public static string ToCommaDelimitedString<T>(this IEnumerable<T> items)
{
    StringBuilder sb = new StringBuilder();
    foreach (var item in items)
    {
        sb.Append(item.ToString());
        sb.Append(',');
    }
    if (sb.Length >= 1) sb.Length--;
    return sb.ToString();
}

แน่นอนหนึ่งสามารถขยายลายเซ็นเป็นตัวคั่นอิสระ ฉันไม่ใช่แฟนตัวยงของการเรียก sb.Remove () และฉันต้องการ refactor ให้เป็นแบบตรงขึ้นในขณะที่วนรอบ IEnumerable และใช้ MoveNext () เพื่อพิจารณาว่าจะเขียนเครื่องหมายจุลภาคหรือไม่ ฉันจะทำเล่น ๆ และโพสต์คำตอบนั้นถ้าฉันเจอมัน


นี่คือสิ่งที่ฉันต้องการในตอนแรก:

public static string ToDelimitedString<T>(this IEnumerable<T> source, string delimiter, Func<T, string> converter)
{
    StringBuilder sb = new StringBuilder();
    var en = source.GetEnumerator();
    bool notdone = en.MoveNext();
    while (notdone)
    {
        sb.Append(converter(en.Current));
        notdone = en.MoveNext();
        if (notdone) sb.Append(delimiter);
    }
    return sb.ToString();
}

ไม่มีอาร์เรย์หรือรายการการจัดเก็บชั่วคราวที่จำเป็นและไม่มีStringBuilder Remove()หรือLength--สับจำเป็น

ในไลบรารีเฟรมเวิร์กของฉันฉันทำการเปลี่ยนแปลงบางอย่างบนลายเซ็นเมธอดนี้ชุดของการรวมdelimiterและconverterพารามิเตอร์ที่มีการใช้","และx.ToString()เป็นค่าเริ่มต้นตามลำดับ


3

หวังว่านี่เป็นวิธีที่ง่ายที่สุด

 string Commaseplist;
 string[] itemList = { "Test1", "Test2", "Test3" };
 Commaseplist = string.join(",",itemList);
 Console.WriteLine(Commaseplist); //Outputs Test1,Test2,Test3

3

ฉันมามากกว่าการสนทนานี้ขณะที่การค้นหาวิธีการที่ดี C # CONCAT_WS()จะเข้าร่วมสตริงเช่นนั้นจะทำด้วยวิธีการของ วิธีนี้แตกต่างจากstring.Join()วิธีการที่จะไม่เพิ่มเครื่องหมายคั่นถ้าสตริงเป็นโมฆะหรือว่างเปล่า

CONCAT_WS (',', tbl.Lastname, tbl.Firstname)

จะกลับเฉพาะในLastnameกรณีที่ชื่อว่างเปล่าในขณะที่

string.Join (",", strLastname, strFirstname)

จะกลับมาstrLastname + ", "ในกรณีเดียวกัน

ต้องการพฤติกรรมแรกฉันเขียนวิธีการดังต่อไปนี้:

    public static string JoinStringsIfNotNullOrEmpty(string strSeparator, string strA, string strB, string strC = "")
    {
        return JoinStringsIfNotNullOrEmpty(strSeparator, new[] {strA, strB, strC});
    }

    public static string JoinStringsIfNotNullOrEmpty(string strSeparator, string[] arrayStrings)
    {
        if (strSeparator == null)
            strSeparator = "";
        if (arrayStrings == null)
            return "";
        string strRetVal = arrayStrings.Where(str => !string.IsNullOrEmpty(str)).Aggregate("", (current, str) => current + (str + strSeparator));
        int trimEndStartIndex = strRetVal.Length - strSeparator.Length;
        if (trimEndStartIndex>0)
            strRetVal = strRetVal.Remove(trimEndStartIndex);
        return strRetVal;
    }

2

ฉันเขียนวิธีการขยายสองสามอย่างเพื่อทำในวิธีที่มีประสิทธิภาพ:

    public static string JoinWithDelimiter(this IEnumerable<String> that, string delim) {
        var sb = new StringBuilder();
        foreach (var s in that) {
            sb.AppendToList(s,delim);
        }

        return sb.ToString();
    }

ขึ้นอยู่กับว่า

    public static string AppendToList(this String s, string item, string delim) {
        if (s.Length == 0) {
            return item;
        }

        return s+delim+item;
    }

3
การใช้ตัวดำเนินการ + เพื่อต่อสตริงไม่ดีเพราะจะทำให้สตริงใหม่ถูกจัดสรรในแต่ละครั้ง ยิ่งไปกว่านั้นแม้ว่า StringBuilder สามารถส่งไปยังสตริงโดยปริยาย แต่บ่อยครั้งที่การทำซ้ำ (ทุกการวนซ้ำของลูป) จะเอาชนะวัตถุประสงค์ของการมีตัวสร้างสตริงเป็นส่วนใหญ่
Daniel Fortunov

2

คุณสามารถใช้.ToArray()บนListsและIEnumerablesแล้วใช้String.Join()ตามที่คุณต้องการ


0

หากสตริงที่คุณต้องการเข้าร่วมอยู่ในรายการวัตถุคุณก็สามารถทำสิ่งนี้ได้เช่นกัน:

var studentNames = string.Join(", ", students.Select(x => x.name));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.