如何将XML文件读入Dictionary <string,list <string>&gt;空元素为空元素</string,list <string>

时间:2010-11-03 05:13:37

标签: c# xml linq dictionary

我有一个xml文件,如:

<root>
  <RowDetails RowName="A" ColumnSize="1">
    <ColumnDetails ColumnName="A1" />
  </RowDetails>
  <RowDetails RowName="B" ColumnSize="2">
    <ColumnDetails ColumnName="B1" />
    <ColumnDetails ColumnName="B2" />
  </RowDetails>
  <RowDetails RowName="C" ColumnSize="3">
    <ColumnDetails ColumnName="C1" />
    <ColumnDetails ColumnName="C2" />
    <ColumnDetails ColumnName="C3" />
  </RowDetails>
</root>

和像这样的词典:

Dictionary<String, List<String>>MyDict = new Dictioanary<String, List<String>>();

我正在阅读MyDict的XML文件,如:

XDocument XDoc = XDocument.Load(Application.StartupPath + @"\foo.xml");
MyDict = XDoc.Descendants("RowDetails").ToDictionary(X => X.Attribute("RowName").Value, 
                                                     X => X.Descendants("ColumnDetails")
                                                           .Select(Y => Y.Attribute("ColumnName").Value).ToList());

现在字典将包含:

"A"           { "A1" }
"B"           { "B1", "B2" }
"C"           { "C1", "C2", "C3" }

但我的问题是我需要所有列表具有相同的计数。应为空条目添加空字符串,因此预期结果为:

"A"           { "A1", "", "" }
"B"           { "B1", "B2", "" }
"C"           { "C1", "C2", "C3" }

如何修改LINQ查询?

请使用LINQ帮助我这样做。

提前致谢。

3 个答案:

答案 0 :(得分:5)

假设您希望在创建MyDict之后将其作为后处理步骤完成,那么基本想法将是:

  1. 找出的每个列表的大小(基于最大列表的数量)。
  2. 根据需要用空字符串填充每个列表,以使其达到正确的大小。

  3. // The required size is the count of the biggest list
    var sizeRequired = MyDict.Values.Max(l => l.Count);
    
    // Pad each list as necessary
    foreach (var list in MyDict.Values)
        list.AddRange(Enumerable.Repeat(string.Empty, sizeRequired - list.Count));
    

    这是一种返回具有所需特征的新词典而不改变原始集合的方法:

     // The required size is the count of the biggest list
    var sizeRequired = MyDict.Values.Max(l => l.Count);
    
    // Each string key should map to a key in the new dictionary
    // Each List<string> value should map to a new list, padded as necessary.
    var paddedDict = MyDict.ToDictionary
      (
         kvp => kvp.Key,
         kvp => kvp.Value
                   .Concat(Enumerable.Repeat(string.Empty, sizeRequired - kvp.Value.Count))
                   .ToList()
      );
    

答案 1 :(得分:2)

您可以在IEnumerable<T>上创建一个扩展方法,以填充到最小尺寸,内联:

public static class IEnumerableExtensions
{
    public static IEnumerable<TSource> PadIfFewerThan<TSource>(
        this IEnumerable<TSource> items,
        int size, TSource padValue = default(TSource))
    {
        int count = 0;

        foreach (var item in items)
        {
            ++count;
            yield return item;
        }

        foreach (var index in Enumerable.Range(count, size - count))
            yield return padValue;
    }
}

您生成的代码如下所示:

var dictionary = doc.Descendants("RowDetails")
    .ToDictionary(
        x => x.Attribute("RowName").Value,
        x => x.Descendants("ColumnDetails")
            .Select(y => y.Attribute("ColumnName").Value)
            .PadIfFewerThan(3, "")
        );

foreach (var entry in dictionary)
    Console.WriteLine(@"""{0}""    {{""{1}""}}",
        entry.Key,
        string.Join(@""",""", entry.Value)
        );
  

“A”{“A1”,“”,“”}   
“B”{“B1”,“B2”,“”}   
“C”{“C1”,“C2”,“C3”}

如果您必须拥有Dictionary<string, List<string>>,而不是此处返回的Dictionary<string, IEnumerable<string>>,只需将.ToList()放回混音中:

var dictionary = doc.Descendants("RowDetails")
    .ToDictionary(
        x => x.Attribute("RowName").Value,
        x => x.Descendants("ColumnDetails")
            .Select(y => y.Attribute("ColumnName").Value)
            .PadIfFewerThan(3)
            .ToList()
        );

答案 2 :(得分:-1)

我不确定“LINQ”中是否有某种方法......我可能也会在C#代码中做你想做的事。

但是,这个要求来自哪里?可能是代码应该在那里改变,它希望你的字典中的所有列表具有相同的大小?