关于c#:将CSV字符串解析为整数数组

Parse CSV string into Array of Integers

我有一个文本框字段输入123145125i,将这个字段分隔成一个整数数组。如果一切分析正确,则验证此字段为真或假。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
private bool chkID(out int[] val)
{
    char[] delimiters = new char[] { ',' };
    string[] strSplit = iconeID.Text.Split(delimiters);  


    int[] intArr = null;
    foreach (string s in strSplit) //splits the new parsed characters
    {
        int tmp;
        tmp = 0;
        if (Int32.TryParse(s, out tmp))
        {
            if (intArr == null)
            {
                intArr = new int[1];
            }
            else
            {
                Array.Resize(ref intArr, intArr.Length + 1);
            }
            intArr[intArr.Length - 1] = tmp;
        }

        if (Int32.TryParse(iconeID.Text, out tmp))
        {
            iconeID.BorderColor = Color.Empty;
            iconeID.BorderWidth = Unit.Empty;

            tmp = int.Parse(iconeID.Text);
            val = new int[1];
            val[0] = tmp;
            return true;
        }


    }
    val = null;
    ID.BorderColor = Color.Red;
    ID.BorderWidth = 2;
    return false;
}

/新代码:private bool chkid(out int[]val)//checkid函数的bool satus{string[]split=srtid.text.split(新字符[1]','];list numbers=new list();解析;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        bool isOk = true;
        foreach( string n in split){
            if(Int32.TryParse( n , out parsed))
                numbers.Add(parsed);
            else
                isOk = false;
        }
        if (isOk){
            strID.BorderColor=Color.Empty;
            strID.BorderWidth=Unit.Empty;
            return true;
        } else{
            strID.BorderColor=Color.Red;
            strID.BorderWidth=2;
            return false;
        }
            return numbers.ToArray();
        }


给定的函数似乎做得太多。这里有一个回答你标题中的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//int[] x = SplitStringIntoInts("1,2,3, 4, 5");

static int[] SplitStringIntoInts(string list)
{
    string[] split = list.Split(new char[1] { ',' });
    List<int> numbers = new List<int>();
    int parsed;

    foreach (string n in split)
    {
        if (int.TryParse(n, out parsed))
            numbers.Add(parsed);
    }

    return numbers.ToArray();
}

编辑(基于您对问题的评论)

您已经定义了这个函数需要做的三件事。现在您只需要为每个方法创建方法。下面是我对如何实现它们的猜测。

1
2
3
4
5
6
7
8
9
10
11
12
13
int[] ValidateIDs(int[] allIDs)
{
    List<int> validIDs = new List<int>(allIDs);

    //remove invalid IDs

    return validIDs.ToArray();
}

void DownloadXmlData(int[] ids)
{
    ...
}

现在您只需执行新功能:

1
2
3
4
5
6
7
void CheckIconeID(string ids)
{
    int[] allIDs = SplitStringIntoInts(ids);
    int[] validIDs = ValidateIDs(allIDs);

    DownloadXmlData(validIDs);
}

我真的想对@austin salonen的答案发表评论,但不太合适。对于所问的问题,这是一个很好的答案,但我希望在csv/int转换部分更广泛地展开讨论。

  • 这是一个小问题,不值得争论,但我会考虑将foreach循环换成一个普通的for循环。你可能会得到更简单的IL(读得更快)。请参阅(http://www.codeproject.com/kb/cs/foreach.aspx,http://msdn.microsoft.com/en-us/library/ms973839.aspx[用于字符串迭代版本1的循环])。
  • 我将创建两种方法——一种是安全的,使用TryParse,只添加"好"值,另一种不是安全的,而是更快的。

建议的"安全"功能(如果不想知道错误的值,则使用重载)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    public static int[] SplitAsIntSafe (this string csvString) {
        List<string> badVals;
        return SplitAsIntSafe(csvString, ',', out badVals);
    }
    public static int[] SplitAsIntSafe (this string delimitedString, char splitChar, out List<string> badVals) {
        int         parsed;
        string[]    split   = delimitedString.Split(new char[1] { ',' });
        List<int>   numbers = new List<int>();
        badVals             = new List<string>();

        for (var i = 0; i < split.Length; i++) {
            if (int.TryParse(split[i], out parsed)) {
                numbers.Add(parsed);
            } else {
                badVals.Add(split[i]);
            }
        }
        return numbers.ToArray();
    }

提议的"快速"功能……

1
2
3
4
5
6
7
8
9
10
11
12
    public static int[] SplitAsIntFast (this string delimitedString, char splitChar) {
        string[]    strArray = delimitedString.Split(splitChar);
        int[]       intArray = new int[strArray.Length];

        if(delimitedString == null) {
            return new int[0];
        }
        for (var i = 0; i < strArray.Length; i++) {
            intArray[i] = int.Parse(strArray[i]);
        }
        return intArray;
    }

无论如何,希望这能帮助别人。


有一个很好的用于分析csv文件的免费库:filehelpers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    using FileHelpers;

    // First declare the record class

    [Delimitedrecord(";")]
    public class SampleType
    {
        public string Field1;
        public int    Field2;
    }


    public void ReadExample()
    {
        FileHelperEngine engine = new FileHelperEngine(typeof(SampleType));

        SampleType[] records;    

        records = (SampleType[]) engine.ReadFile("source.txt");

        // Now"records" array contains all the records in the
        // sourcefile and can be acceded like this:

        int sum = records[0].Field2 + records[1].Field2;
    }


检查这个文件帮助器和csv阅读器可能是值得的。

希望他们能帮助你…当心,汤姆


在.NET 2.0中,您可以编写

1
2
3
4
5
6
7
8
9
10
11
12
13
string test ="123,14.5,125,151,1.55,477,777,888";

bool isParsingOk = true;


int[] results = Array.ConvertAll<string,int>(test.Split(','),
    new Converter<string,int>(
        delegate(string num)
        {
            int r;
            isParsingOk &= int.TryParse(num, out r);
            return r;
        }));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public bool ParseAndCheck(string source,
    out IList<int> goodItems, out IList<string> badItems)
{
    goodItems = new List<int>();
    badItems = new List<string>();

    foreach (string item in source.Split(','))
    {
        int temp;
        if (int.TryParse(item, out temp))
            goodItems.Add(temp);
        else
            badItems.Add(item);
    }

    return (badItems.Count < 1);
}


这很简单,我认为效果很好。它只返回有效数字:

1
2
3
4
5
6
7
static int[] SplitStringIntoInts(string list)
{            
    int dummy;            
    return (from x in list.Split(',')
            where int.TryParse(x.ToString(), out dummy)
            select int.Parse(x.ToString())).ToArray();          
}