2

我有一个包含在包含以下值的字典中的列表

value a
value b
value c
value 1, value 2, value3
value d

我想要的最终结果是

value a
value b
value c
value 1
value 2
value 3
value d

问题是遍历字典并尝试更改集合将不起作用,因为我试图在循环遍历它时对其进行修改

string[] ar;
        foreach (var kvp in dict)
        {
            if (kvp.Key == "STAR-016")
            {
                foreach (var v in kvp.Value)
                {
                    if (v.Contains(','))
                    {
                        ar = v.Split(',');
                        foreach (var a in ar)
                        {
                            kvp.Value.Add(a);
                        }
                    }
                }
            }
        }

我怎样才能得到想要的结果?

4

5 回答 5

3

尝试使用 LINQ:

var list = new List<string>()
{
    "value a",
    "value b",
    "value 1, value 2, value 3",
    "value c"
};

/* THIS IS THE IMPORTANT PART: */
/* Replace list with kvp.Value */
list = list.SelectMany( 
         i => i.Split( ',' ).Select( v => v.Trim() ) 
       ).ToList();

foreach ( var item in list )
    Console.WriteLine( item );

输出:

值 a
值 b
值 1
值 2
值 3
值 c

要在您的代码中使用它:

foreach (var kvp in dict)
{
    if (kvp.Key == "STAR-016")
    {
        var newList = 
            kvp.Value.SelectMany(
                i => i.Split( ',' ).Select( v => v.Trim() )
            );
        kvp.Value.Clear();
        kvp.Value.AddRange(newList);
    }
}

感谢@Mudu 指出更简单的i =>语法

于 2013-02-14T12:56:54.110 回答
2

您可以循环List使用for而不是foreach修改项目

for (int i = 0; i < kvp.Value.Count; i++)
{
    if (kvp.Value[i].Contains(','))
        ...
}
于 2013-02-14T12:50:18.887 回答
2

假设这只是一个示例,并且您实际上不仅想要一个键STAR-016,而且想要所有值(即 a List<string>)包含逗号的地方:

Dictionary<string, List<String>> dict = new Dictionary<string, List<String>>();
dict.Add("STAR-016", new List<string>() { 
    "value a", "value b", "value c", "value 1, value 2, value 3", "value d"
});

foreach (var kvp in dict)
{
    for (int i = kvp.Value.Count - 1; i >= 0; i--)
    {
        string str = kvp.Value[i];
        if (str.Contains(','))
        {
            var parts = str.Split(',').Select(p => p.Trim());
            kvp.Value.RemoveAt(i);
            kvp.Value.InsertRange(i, parts);
        }
    }
}

演示

我从结尾循环到开头以避免并发症,因为InsertRange会添加新的字符串,这会增加Count.
我正在使用RemoveAt添加的新字符串(用逗号分隔的每个部分一个)用逗号替换字符串。我使用InsertRange而不是AddRange因为你想保持订单。

结果:

value a
value b
value c
value 1
value 2
value 3
value d
于 2013-02-14T12:53:30.340 回答
2

您应该能够使用SelectMany.

dict["STAR-016"] = dict["STAR-016"].SelectMany(s=>s.Split(',')).ToList();

这会将您的密钥列表替换为以逗号分隔字符串的列表,如果字符串不包含逗号,它只会返回字符串。StringSplitOptions.RemoveEmptyEntries如果您不希望连续逗号产生空字符串,您也可以考虑使用。

于 2013-02-14T13:04:14.913 回答
1

(编辑:juharr 的https://stackoverflow.com/a/14875503/17713与内置 LINQ 功能和更多功能风格基本相同,这在描述实际问题时通常更具表现力)

我会采用一种yield不会修改原始集合的方法。List<string> orig下面是一个对也可能在字典中的 a 进行操作的示例代码:

public static void Main()
{
    List<string> orig = new List<string>()
    {
        "value a",
        "value b",
        "value c",
        "value 1, value 2, value 3",
        "value d"
    };

    var result = Flatten(orig).ToList();

    foreach(string s in result)
    {
        Console.WriteLine(s);
    }
}

private static IEnumerable<string> Flatten(IList<string> orig)
{
    foreach(string s in orig)
    {
        // split anyway, if there's no colon you just get a one-element
        // array containing s, see
        // http://msdn.microsoft.com/en-us/library/b873y76a.aspx
        foreach(string v in s.Split(','))
        {
            yield return v.Trim();
        }
    }
}

在字典中,您可以将结果替换为原始值:

dict["STAR-016"] = Flatten(dict["STAR-016"]).ToList()

旁注:上面的代码STAR-016直接找到而不是使用foreach更慢的 a 。如果您没有缩短代码并且实际上只是在查找,STAR-016我建议您使用这种字典查找方式。

于 2013-02-14T12:58:03.610 回答