代码之家  ›  专栏  ›  技术社区  ›  user372724

NET中的字符串拆分器

  •  5
  • user372724  · 技术社区  · 14 年前

    我有下面的字符串

    P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO
    

    我需要输出为

    P
    
    MV
    
    A1ZWR
    
    MAV#(X,,)
    
    PV
    
    MOV#(X,12,33)
    
    LO
    

    可以看出,用“,”分开很容易,但问题来了

    当它是MAV#(X,,)或MOV#(X,12,33)类型时。

    10 回复  |  直到 14 年前
        1
  •  4
  •   Martin JonáÅ¡    14 年前

    因为没有这样的解决方案只使用LINQ,我很感兴趣它看起来如何,所以我想到了这个。但我不建议在生产代码中使用它。实际上,我希望它会更好,但由于嵌套的parenthenes需要处理,我不得不引入可变的状态变量。

    string data = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO";
    
    int depth = 0;
    int group = 0;
    
    var result = data
        .GroupBy(x => { 
            if (x == '(') depth++;
            if (x == ')') depth--;
            if (x == ',' && depth == 0) group++; 
            return group; })
        .Select(x => new String(x.ToArray()).Trim(' ', ','))
    
        2
  •  8
  •   Guffa    14 年前

    您可以使用正则表达式来匹配分隔符之间的值,并指定Paranthese中的所有内容都是该值的一部分。例子:

    string data = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO";
    
    foreach (Match m in Regex.Matches(data, @"\s*((\(.*?\)|[^,])*)(,|$)")) {
      Console.WriteLine(m.Groups[1].Value);
    }
    

    P
    MV
    A1ZWR
    MAV#(X,,)
    PV
    MOV#(X,12,33)
    LO
    
        3
  •  4
  •   Catalin DICU    14 年前
    string input = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO";
    IList<string> parts = new List<string>();
    int paranthesisCount = 0;
    int lastSplitIndex = 0;
    for (int i = 0; i < input.Length; i++)
    {
        if (input[i] == '(')
        {
            paranthesisCount++;
            continue;
        }
        if (input[i] == ')')
        {
            paranthesisCount--;
            continue;
        }
        if (input[i] == ',' && paranthesisCount == 0)
        {
            parts.Add(input.Substring(lastSplitIndex, i - lastSplitIndex));
            lastSplitIndex = i + 1;
        }
    }
    if (input.Length - lastSplitIndex > 0)
    {
        parts.Add(input.Substring(lastSplitIndex, input.Length - lastSplitIndex));
    }
    
        4
  •  2
  •   Douglas    14 年前

    最好的办法是为数据编写解析器。查找CSV解析库,您可以修改一个以支持 #(...) "..." 没有太多困难。

        5
  •  1
  •   Arcturus    14 年前

    如何循环和检测商标字符,如 ( ) :

    string[] test = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO".Split(',');
    
    bool insideElement = false;
    string insideElementResult = "";
    List<string> result = new List<string>();
    foreach (string s in test)
    {
        //Determine context:
        if (s.IndexOf("(") > -1)
            insideElement = true;
    
        //Determine where to add my nice string
        if (!insideElement)
            result.Add(s);
        else
            insideElementResult += s;
    
        //Determine if contact has ended:
        if (s.IndexOf(")") > -1)
        {
            insideElement = false;
            result.Add(insideElementResult);
            insideElementResult = null;
        }
        else if (insideElement)
        {
            insideElementResult += ",";
        }
    
    }
    

    结果:

        [0] "P" string
        [1] "MV"    string
        [2] "A1ZWR" string
        [3] "MAV#(X,,)" string
        [4] " PV"   string
        [5] "MOV#(X,12,33)" string
        [6] "LO"    string
    

    当然,不像regex那么花哨,而且会在内圆括号上中断,但是嘿,它工作了;)

        6
  •  1
  •   schoetbi    14 年前

    为了理解字符串,解析器也会有所帮助。最简单的解析器是递归解析器。这样你就可以确定

    1. 没有错误的裂口
    2. 所有标记都是正确的(这可能会有所帮助,但取决于应用程序)

    ANTLR . 如果对你有帮助的话就去看看。在这个问题上,这可能是一种过分的做法。好好想想。

        7
  •  0
  •   schoetbi    14 年前

     P~MV~A1ZWR~MAV#(X,,)~ PV~MOV#(X,12,33)~LO
    

    甚至一个不可见的字符(0x00?)

        8
  •  0
  •   MunkiPhD    14 年前

    否则,您可能需要拆分字符串并查看bucket,同时查找问题并执行任何必要的合并和进一步拆分。

        9
  •  0
  •   Matt Ellen Bipin Vayalu    14 年前

    此函数将拉出所有标记,确保标记之间没有双逗号,并确保所有括号都是闭合的。有点长。

    IEnumerable<string> Tokenise(string input)
    {
        const char tokenlimiter = ',';
        const char funcstart = '#';
        const char funcend = ')';
        StringBuilder token = new StringBuilder(5);
        bool gotfunc = false;
        bool gotone = false;
        int pos = 0;
        int opened = 0;
        foreach(char c in input)
        {
            if (c == funcstart)
            {
                gotfunc = true;
                opened++;
            }
            if(c == funcend)
            {
                gotfunc = false;
                opened--;
            }
            if(!gotfunc && c == tokenlimiter)
            {
                gotone = true;
                if(token.Length == 0)
                {
                    throw new ArgumentException("Blank instruction at " + pos, input);
                }
                yield return token.ToString();
            }
            if(gotone)
            {
                token = new StringBuilder(5);
                gotone = false;
            }
            else
            {
                token.Append(c);    
            }
            if(pos == input.Length - 1)
            {
                if (!gotfunc && opened == 0 && c != tokenlimiter)
                {
                    yield return token.ToString();
                }
                else if (gotfunc || opened != 0)
                {
                    throw new ArgumentException("Broken function", input);
                }
                else
                {
                    throw new ArgumentException("Blank instruction at " + pos, input);
                }
            }
            pos++;
        }
    
    }
    
        10
  •  0
  •   user372724 user372724    14 年前
    private static void CreateListString(string s)
    {
    string[] splits = s.Split(new char[] { ',' });
    List<string> strs = new List<string>();
    bool isLimiterSeen = false;
    StringBuilder str = null;
    for (int i = 0; i < splits.Length; i++)
    {
    if (splits[i].Contains("#("))
    {
    isLimiterSeen = true;
    str = new StringBuilder();
    }
    if (!isLimiterSeen)
    strs.Add(splits[i]);
    else
    {
    str = str.Append("," + splits[i]);
    if (splits[i].EndsWith(")"))
    {
    if (str.ToString().StartsWith(","))
    strs.Add(str.ToString().Substring(1));
    else
    strs.Add(str.ToString());
    isLimiterSeen = false;
    str = null;
    }
    }
    }
    }