使用LINQ将字符串拆分为元组?

时间:2017-02-09 13:39:30

标签: c# linq

给定一个像"name:Dave"这样的字符串我想转换为Tuple<string,string>是否有一种简洁的方法可以使用LINQ进行内联,而不是首先获取数组然后解析它?

我正在解析我的app.config文件中的一些配置数据,如下所示:

<Data>
  <add key="John" value="instrument:guitar"/>
  <add key="Paul" value="instrument:bass"/>
  <add key="George" value="instrument:guitar"/>
  <add key="Ringo" value="instrument:drums"/>
</Data>

我要将其转换为Dictionary<string,tuple<string,string>>(我知道这是一个奇怪的数据结构!)

从一些代码开始:

            var x = ((ConfigurationManager.GetSection("Data") as Hashtable))
                .Cast<System.Collections.DictionaryEntry>()
                .ToDictionary(n => n.Key.ToString(), n => something(n.Value.ToString().Split(':')));

我想知道是否有一种简洁的LINQ方式在线执行此操作而不是编写一个实用程序函数来从String.Split的数组中获取单个元组?

2 个答案:

答案 0 :(得分:4)

var source = new Dictionary<string, string>(){ { "John", "instrument:guitar" } };
var tuple = source.Select(x => new { key = x.Key, values = x.Value.Split(':') }).Select(y => new Tuple<string, string>(y.key, y.values[1])).ToList();

答案 1 :(得分:2)

你的字符串基本上是XML所以我只想使用XmlDocument命名空间中的System.Xml来解析它。然后你可以使用GetElementsByTagName因为你要检索的所有值都有相同的标记(<add />),然后用它来创建这样的字典:

string @xml = @"<Data>
<add key=""John"" value=""instrument:guitar""/>
<add key=""Paul"" value=""instrument:bass""/>
<add key=""George"" value=""instrument:guitar""/>
<add key=""Ringo"" value=""instrument:drums""/>
</Data>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(@xml);
var dict = new Dictionary<string, Tuple<string, string>>();
doc.GetElementsByTagName("add")
    .OfType<XmlElement>()
    .Select(element =>
    {
        string key = element.Attributes["key"].Value;
        string[] value = element.Attributes["value"].Value.Split(':');
        dict.Add(key, new Tuple<string, string>(value[0], value[1]));
        return dict.Last();
    });
return dict;

可以缩短为以下内容:

XmlDocument doc = new XmlDocument();
doc.LoadXml(@xml);
Dictionary<string, Tuple<string, string>> dict = doc.GetElementsByTagName("add")
    .OfType<XmlElement>()
    .Select(element => new Tuple<string, string[]>(element.Attributes["key"].Value, element.Attributes["value"].Value.Split(':')))
    .ToDictionary(element => element.Item1, element => new Tuple<string, string>(element.Item2[0], element.Item2[1]));

return dict;

甚至更短:

XmlDocument doc = new XmlDocument();
doc.LoadXml(@xml);
Dictionary<string, Tuple<string, string>> dict = doc.GetElementsByTagName("add")
    .OfType<XmlElement>()
    .ToDictionary(element => element.Attributes["key"].Value, element => new Tuple<string, string>(element.Attributes["value"].Value.Split(':')[0], element.Attributes["value"].Value.Split(':')[1]));
return dict;

编辑: (问题编辑后)

您可以使用包含System.Configuration对象的ConfigurationManager库,并执行以下操作:

ConfigurationManager.AppSettings.AllKeys.ToDictionary(
    key =>
        key,
    key =>
        new Tuple<string, string>(
            ConfigurationManager.AppSettings[key].Split(':')[0],
            ConfigurationManager.AppSettings[key].Split(':')[1]
        )
);

但您必须确保app.config仅包含您要使用此方法处理的键。如果您尝试处理类似于<add key="Willy" value="noinstrument" />的行,那么该方法将会中断。