开发者

Parse CSV string into Array of Integers

I have a text box field inputs 123,145,125 I to separate this field into an array of integers. And validate this field true or false if everything is parsed right.

CODE:

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))
        {
     开发者_JAVA百科       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;
}

//new Code: private bool chkID(out int[] val) //bool satus for checkID function { string[] split = srtID.Text.Split(new char[1] {','}); List numbers = new List(); int parsed;

        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();
        }


The given function seems to do too much. Here's one that answers the question implied by your title:

//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();
}

EDIT (based on your comment on the question)

You've defined the three things this function needs to do. Now you just need to create methods for each. Below are my guesses for how you could implement them.

int[] ValidateIDs(int[] allIDs)
{
    List<int> validIDs = new List<int>(allIDs);

    //remove invalid IDs

    return validIDs.ToArray();
}

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

Now you just execute your new functions:

void CheckIconeID(string ids)
{
    int[] allIDs = SplitStringIntoInts(ids);
    int[] validIDs = ValidateIDs(allIDs);

    DownloadXmlData(validIDs);
}


I really wanted to comment on @Austin Salonen's answer, but it didn't fit. It is a great answer for the question asked, but i wanted to expand the discussion a bit more generally on csv/int conversion part.

  • It's small point, not worth much debate but I would consider swapping the foreach loop for a plain for loop. You'll likely end up with simpler IL (read faster). See (http://www.codeproject.com/KB/cs/foreach.aspx, http://msdn.microsoft.com/en-us/library/ms973839.aspx [Use For Loops for String Iteration—version 1]).
  • I would create two methods -- one that is safe and uses TryParse and only adds the "good" values, another that is not as safe, but faster.

Proposed "safe" function (with overload in case you don't want to know the bad values)...

    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();
    }

Proposed "fast" function ....

    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;
    }

Anyway, hope this helps someone.


It might be worth your while to check out this FileHelper and also CSV Reader

Hope they will help you... Take care, Tom


There is a good free library for parsing CSV files: FileHelpers

    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;
    }


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);
}


In .NET 2.0 you could write

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;
        }));


This is simple and I think works pretty well. It only return valid numbers:

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();           
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜