IList<string>
또는 에서 쉼표로 구분 된 문자열 값 목록을 만드는 가장 깨끗한 방법은 무엇입니까 IEnumerable<string>
?
String.Join(...)
에서 작동 string[]
하므로 문자열 배열로 변환 IList<string>
하거나 IEnumerable<string>
쉽게 변환 할 수없는 경우 작업하기가 번거로울 수 있습니다 .
IList<string>
또는 에서 쉼표로 구분 된 문자열 값 목록을 만드는 가장 깨끗한 방법은 무엇입니까 IEnumerable<string>
?
String.Join(...)
에서 작동 string[]
하므로 문자열 배열로 변환 IList<string>
하거나 IEnumerable<string>
쉽게 변환 할 수없는 경우 작업하기가 번거로울 수 있습니다 .
답변:
.NET 4 이상
IList<string> strings = new List<string>{"1","2","testing"};
string joined = string.Join(",", strings);
세부 및 사전 .Net 4.0 솔루션
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());
후자는 약간 한 입입니다 :)
에 대한 다른 질문이 성능을 포함하여 (이에 국한되지 않음)처럼 정확히 - 이것은 아주 성능이 좋은뿐만 아니라 그것을 할 수있는 간단한 방법이 될 가능성이 있으며, 이 중 하나를 .
.NET 4.0부터에서 사용할 수있는 과부하가 더 string.Join
많으므로 실제로 다음과 같이 작성할 수 있습니다.
string joined = string.Join(",", strings);
훨씬 간단합니다 :)
List<T>
됩니다. 이것이 바로 그 일 입니다. 왜 바퀴를 재발 명합니까?
ToList
. string myStr = string.Join(",", foo.Select(a => a.someInt.ToString()))
그래도 사용하는 것이 좋습니다.
참고로, .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)
str = emps.Select(e => e.SSN).Join(",")
이 작업을 수행하는 가장 쉬운 방법은 LINQ Aggregate
방법을 사용하는 것입니다.
string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)
Func<StringBuilder,string,StringBuider>
. 그런 다음 ToString()
반환 된 StringBuilder를 호출 하십시오. 물론 예쁘지는 않습니다 :)
input.Count
해야합니다 이상 1
쉼표로 구분 된 문자열 값 목록을 만드는 가장 깨끗한 방법은 다음과 같습니다.
string.Join<string>(",", stringEnumerable);
전체 예는 다음과 같습니다.
IEnumerable<string> stringEnumerable= new List<string>();
stringList.Add("Comma");
stringList.Add("Separated");
string.Join<string>(",", stringEnumerable);
도우미 기능을 만들 필요가 없으며 .NET 4.0 이상에 내장되어 있습니다.
실적을 기준으로 비교하면 "루프, sb. 추가 및 백스텝"입니다. 실제로 "다음 열거 및 수동 이동"도 동일합니다 (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();
}
}
이 토론에 조금 늦게 도착했지만 이것이 저의 공헌입니다. I는 한 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 길이를 1 씩 줄이며 CSV 문자열을 반환합니다.
Append()
문자열 + 쉼표를 추가 하기 위해 여러 개를 사용하도록 이것을 업데이트했습니다 . James의 피드백에서 Reflector를 사용하여을 살펴 보았습니다 StringBuilder.AppendFormat()
. 밝혀 AppendFormat()
용도는 모두 StringBuilder는 여러 사용하는 것보다 이러한 맥락에서 덜 효율적 형식 문자열 구성하기 Appends()
'들.
다음과 같은 유틸리티 함수가 있습니다 :
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() );
다른 방법으로 나열된 메소드 중 하나를 사용하여 배열로 변환 한 후 다음과 같은 것을 사용할 수도 있습니다.
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();
}
}
}
편집 : 여기 또 다른 예가 있습니다.
이 기사에서 발생하기 전에이 문제를 해결했습니다. 내 솔루션은 다음과 같습니다.
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));
내 대답은 위의 집계 솔루션과 같지만 명시 적 대리자 호출이 없으므로 호출 스택이 적어야합니다.
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 () 호출의 팬이 아니며 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()
기본값으로 사용했습니다.
잘만되면 이것이 가장 간단한 방법입니다
string Commaseplist;
string[] itemList = { "Test1", "Test2", "Test3" };
Commaseplist = string.join(",",itemList);
Console.WriteLine(Commaseplist); //Outputs Test1,Test2,Test3
MySql 메서드와 같이 문자열을 조인하는 좋은 C # 메서드를 검색하는 동안이 토론을 진행했습니다 CONCAT_WS()
. 이 방법은 string.Join()
문자열이 NULL이거나 비어있는 경우 구분 기호를 추가하지 않는다는 점에서 방법과 다릅니다 .
CONCAT_WS ( ',', tbl. 성, tbl. 이름)
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;
}
효율적인 방법으로 몇 가지 확장 방법을 작성했습니다.
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;
}
public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)