[C#] 일반 목록을 CSV 문자열로 변환

정수 값 목록 (목록)이 있고 쉼표로 구분 된 값의 문자열을 생성하고 싶습니다. 이는 목록의 모든 항목이 단일 쉼표 제거 목록으로 출력됩니다.

내 생각은 … 1. 목록을 메소드에 전달하십시오. 2. stringbuilder를 사용하여 목록을 반복하고 쉼표를 추가하십시오. 3. 마지막 문자를 테스트하고 쉼표 인 경우 삭제하십시오.

당신의 생각은 무엇입니까? 이것이 최선의 방법입니까?

앞으로 정수 (현재 계획)뿐만 아니라 문자열, long, double, bool 등을 처리하려면 코드가 어떻게 변경됩니까? 모든 유형의 목록을 허용한다고 생각합니다.



답변

프레임 워크가 이미 우리를 위해하는 일이 놀랍습니다.

List<int> myValues;
string csv = String.Join(",", myValues.Select(x => x.ToString()).ToArray());

일반적인 경우 :

IEnumerable<T> myList;
string csv = String.Join(",", myList.Select(x => x.ToString()).ToArray());

보시다시피 사실상 다르지 않습니다. 쉼표가 포함 된 경우 실제로 x.ToString()따옴표로 묶어야 할 수도 있습니다 (예 :)."\"" + x.ToString() + "\""x.ToString()

약간의 변형에 대한 흥미로운 내용 은 Eric Lippert의 블로그에서 Comma Quibbling 을 참조하십시오 .

참고 : 이것은 .NET 4.0이 공식적으로 출시되기 전에 작성되었습니다. 이제 우리는 말할 수 있습니다

IEnumerable<T> sequence;
string csv = String.Join(",", sequence);

과부하 사용 String.Join<T>(string, IEnumerable<T>). 이 방법은 각 요소 x를에 자동으로 투사 합니다 x.ToString().


답변

3.5에서는 여전히이 작업을 수행 할 수있었습니다. 훨씬 간단하고 람다가 필요하지 않습니다.

String.Join(",", myList.ToArray<string>());


답변

IEnumerable에서 호출 할 수있는 확장 메서드를 만들 수 있습니다.

public static string JoinStrings<T>(
    this IEnumerable<T> values, string separator)
{
    var stringValues = values.Select(item =>
        (item == null ? string.Empty : item.ToString()));
    return string.Join(separator, stringValues.ToArray());
}

그런 다음 원래 목록에서 메소드를 호출하면됩니다.

string commaSeparated = myList.JoinStrings(", ");


답변

사용할 수 있습니다 String.Join.

String.Join(
  ",",
  Array.ConvertAll(
     list.ToArray(),
     element => element.ToString()
  )
);


답변

본문 에서 문자열 목록 대신 사용자 정의 클래스 객체 목록을 변환하려는 경우 클래스의 csv 행 표현으로 클래스의 ToString 메소드를 대체하십시오.

Public Class MyClass{
   public int Id{get;set;}
   public String PropertyA{get;set;}
   public override string ToString()
   {
     return this.Id+ "," + this.PropertyA;
   }
}

그런 다음 헤더 코드가있는이 클래스 목록을 CSV로 변환하는 데 다음 코드를 사용할 수 있습니다

string csvHeaderRow = String.Join(",", typeof(MyClass).GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToArray<string>()) + Environment.NewLine;
string csv= csvHeaderRow + String.Join(Environment.NewLine, MyClass.Select(x => x.ToString()).ToArray());


답변

@Frank가 제공 한 링크의 코드로 .NET Generic List에서 CSV 파일을 만들면, 코드를 수정하여 모든 줄을 끝내는 약간의 문제 가 발생했습니다.

/// <summary>
/// Creates the CSV from a generic list.
/// </summary>;
/// <typeparam name="T"></typeparam>;
/// <param name="list">The list.</param>;
/// <param name="csvNameWithExt">Name of CSV (w/ path) w/ file ext.</param>;
public static void CreateCSVFromGenericList<T>(List<T> list, string csvCompletePath)
{
    if (list == null || list.Count == 0) return;

    //get type from 0th member
    Type t = list[0].GetType();
    string newLine = Environment.NewLine;

    if (!Directory.Exists(Path.GetDirectoryName(csvCompletePath))) Directory.CreateDirectory(Path.GetDirectoryName(csvCompletePath));

    if (!File.Exists(csvCompletePath)) File.Create(csvCompletePath);

    using (var sw = new StreamWriter(csvCompletePath))
    {
        //make a new instance of the class name we figured out to get its props
        object o = Activator.CreateInstance(t);
        //gets all properties
        PropertyInfo[] props = o.GetType().GetProperties();

        //foreach of the properties in class above, write out properties
        //this is the header row
        sw.Write(string.Join(",", props.Select(d => d.Name).ToArray()) + newLine);

        //this acts as datarow
        foreach (T item in list)
        {
            //this acts as datacolumn
            var row = string.Join(",", props.Select(d => item.GetType()
                                                            .GetProperty(d.Name)
                                                            .GetValue(item, null)
                                                            .ToString())
                                                    .ToArray());
            sw.Write(row + newLine);

        }
    }
}


답변

게시물 에서 자세히 설명합니다 . 간단한 설명과 함께 여기에 코드를 붙여 넣습니다.

헤더 행을 만드는 방법은 다음과 같습니다. 속성 이름을 열 이름으로 사용합니다.

private static void CreateHeader<T>(List<T> list, StreamWriter sw)
    {
        PropertyInfo[] properties = typeof(T).GetProperties();
        for (int i = 0; i < properties.Length - 1; i++)
        {
            sw.Write(properties[i].Name + ",");
        }
        var lastProp = properties[properties.Length - 1].Name;
        sw.Write(lastProp + sw.NewLine);
    }

이 방법은 모든 값 행을 만듭니다.

private static void CreateRows<T>(List<T> list, StreamWriter sw)
    {
        foreach (var item in list)
        {
            PropertyInfo[] properties = typeof(T).GetProperties();
            for (int i = 0; i < properties.Length - 1; i++)
            {
                var prop = properties[i];
                sw.Write(prop.GetValue(item) + ",");
            }
            var lastProp = properties[properties.Length - 1];
            sw.Write(lastProp.GetValue(item) + sw.NewLine);
        }
    }

그리고 그것들을 모아서 실제 파일을 만드는 방법이 있습니다.

public static void CreateCSV<T>(List<T> list, string filePath)
    {
        using (StreamWriter sw = new StreamWriter(filePath))
        {
            CreateHeader(list, sw);
            CreateRows(list, sw);
        }
    }