正确地将字符串转换为在C#中具有不规则csv的字典?

时间:2018-10-09 08:39:17

标签: c# asp.net json linq

我在aspx页面上有一个从用户输入返回的字符串。 C#代码的第一块工作正常,我可以访问每个字典键值对。

string strsvresponse = "name:bob, age:22, city:Wolverhampton, state:West, Midlands, country:United Kingdom"
var dictusrdata = strsvresponse.Split(',')
.Select(x => x.Split(':'))
.ToDictionary(x => x[0], x => x[1]);

但是,微妙的区别是另一个用户决定在状态字段中添加一个逗号,该逗号引发错误“索引在数组的边界之外”。

string strsvresponse = "name:bob, age:22, city:Wolverhampton, state:West, Midlands, UK, country:United Kingdom"
var dictusrdata = strsvresponse.Split(',')
.Select(x => x.Split(':'))
.ToDictionary(x => x[0], x => x[1]);

我无法阻止用户这样做,但是我想知道是否有更好的方法来编码字符串以获取键值对或访问field:value数据?

谢谢 G

4 个答案:

答案 0 :(得分:3)

首先:您的格式不明确。使用众所周知且广泛支持的格式:CSV,JSON,XML或更严格的格式。

如果您不能更改格式,则必须承担一些责任。假设标签是用逗号和空格分隔的单个单词:

var regex = "\\w+:.*?(?=(, \\w+:|$))";
string strsvresponse =
    "name:bob, age:22, city:Wolverhampton, state:West, Midlands, UK, country:United Kingdom";

var dictusrdata = Regex.Matches(strsvresponse, regex)
    .OfType<Match>()
    .Select(a => a.Value.Split(':'))
    .ToDictionary(a => a[0], a => a[1]);

正则表达式\w+:.*?(?=(, \w+:|$))解释:

\w+ - any word
   : - followed by : (this is TAG)
    .*? - eat all chars lazily

(?= - lookahead assertion
   (
    , \w+: - make sure match is followed by [comma][space]TAG
   | - or
    $ - end of string
   )
) 

答案 1 :(得分:1)

这是一种实现方法:

string strsvresponse = "name:bob, age:22, city:Wolverhampton, state:West, Midlands, UK, country:United Kingdom";
var result = new Dictionary<String, String>();
var pairs = strsvresponse.Split(',');
for (int i = pairs.Count()-1; i >= 0; i--)
{
    var pair = pairs[i].Split(':');
    if (pair.Length == 2)
    {
        result.Add(pair[0].Trim(), pair[1].Trim());
    }
    else
    {
        pairs[i-1] = pairs[i-1] + pairs[i]; // add comma here if needed
    }
}
return result;

这将为您提供这样的结果

Dump of dictionary

请注意,state吞下了多余的逗号。您可以根据需要将其重新添加-参见评论。同样,这假设逗号后但没有冒号的单词确实属于前一对。

我也同意其他评论者的意见,这是一种损坏的CSV格式,您需要从源头上解决问题-不允许进行此输入。但是解决这个小难题很有趣。

这是一个DotnetFiddle

答案 2 :(得分:0)

您可以执行以下操作:

Dictionary<string, string> dic = new Dictionary<string, string>();
string strsvresponse = "name:bob, age:22, city:Wolverhampton, state:West Midlands, dfgdfgfdg,country: United Kingdom";

//First split by ','
var response = strsvresponse.Split(',');

foreach (var item in response)
{
    //After splitting by ':' check if
    //you have necessary values to create KeyValuePair
    var dicVals = item.Split(':');
    if(dicVals.Length != 2)
    {
        //TODO: Log error
        continue;
    }
    dic.Add(dicVals[0], dicVals[1]);
}

答案 3 :(得分:0)

另一种方法是编写自定义解析器,这样您就可以编写自定义逻辑并控制数据处理。

        string strsvresponse = "name:bob, age:22, city:Wolverhampton, state:West Midlands, UK, country: United Kingdom";

        string iKey = string.Empty;
        string iValue = string.Empty;
        int iMode = 0;
        Dictionary<string, string> dictusrdata = new Dictionary<string, string>();
        for (int i = 0; i < strsvresponse.Length; i++)
        {
            if (iMode == 0)
            {
                if (strsvresponse[i] == ':')
                {
                    iMode = 1;
                } 
                else if (strsvresponse[i] == ',')
                {
                    iKey = string.Empty;
                    iValue = string.Empty;
                }
                else
                {
                    iKey += strsvresponse[i];
                }
            }
            else
            {
                if (strsvresponse[i] == ',')
                {
                    dictusrdata.Add(iKey.Trim(), iValue.Trim());
                    iKey = string.Empty;
                    iValue = string.Empty;
                    iMode = 0;
                }
                else
                {
                    iValue += strsvresponse[i];
                }
            }
        }

        //add last value
        if (!string.IsNullOrEmpty(iKey))
        {
            dictusrdata.Add(iKey.Trim(), iValue.Trim());
        }