如果使用LINQ包含具有相同键的项目,如何更新Dictionary?

时间:2014-01-08 13:39:15

标签: c# linq dictionary

我有下一个功能:

private static Dictionary<string, object> FromCookies(HttpCookieCollection cc)
{
return (from string cookie in cc.AllKeys select new { Name = cookie, Value = (object)cc[cookie] }).ToDictionary(kvp => kvp.Name, kvp => kvp.Value, StringComparer.InvariantCultureIgnoreCase);
}

但是当我构建时,编译器说我:

System.ArgumentException: An item with the same key has already been added.

但我需要重写这个项目。我怎么能用LINQ做到这一点?我很抱歉我的愚蠢问题,如果这么容易回答。

4 个答案:

答案 0 :(得分:1)

我可能会犯错,但我认为你不能使用LINQ来做到这一点。 return语句创建一个新的字典,该字典将从cookie集合中的对象创建。如果此集合包含多个具有相同名称的对象,则表明您遇到了问题。

我认为实现这一目标的最佳方法是迭代cookie集合,手动为字典创建对象,并使用索引器语法将它们设置在字典中:

dictionary[cookiename] = cookieValue;

干杯!

亚历

答案 1 :(得分:0)

您可以选择 distinct Cookie以避免重复的字典键。但是,当然,结果字典中只有一个值。即如果您有"Hello""hello""HELLO"等Cookie,则如果您使用忽略大小写比较,则无法放置所有这些键。下面的解决方案仅选择与忽略大小写相同的第一个值(在这种情况下将仅添加"Hello"个键):

return (from string cookie in cc.AllKeys.Distinct(StringComparer.InvariantCultureIgnoreCase) // here
        select new { 
            Name = cookie, 
            Value = (object)cc[cookie] 
        })
        .ToDictionary(kvp => kvp.Name, kvp => kvp.Value);

BTW代码可以简化为

return cc.AllKeys // use .Cast<string>() if need
         .Distinct(StringComparer.InvariantCultureIgnoreCase) 
         .ToDictionary(cookie => cookie,
                       cookie => (object)cc[cookie]);

因此,您将避免匿名对象的创建。

答案 2 :(得分:0)

也许你有重复的名字,你可以先使用GroupBy StringComparer {/ 1>}

private static Dictionary<string, object> FromCookies(HttpCookieCollection cc)
{
    var result = cc.AllKeys
        .Select(cookie => new { Name = cookie, Value = (object)cc[cookie] })
        .GroupBy(x => x.Name, StringComparer.InvariantCultureIgnoreCase)
        .ToDictionary(g => g.Key, g => g.First().Value, StringComparer.InvariantCultureIgnoreCase);
    return result;
}

我从重复项中取出第一个值。但你可以改变逻辑。

答案 3 :(得分:0)

您总是可以使用IEnumerable的KeyValuePairs,这将允许具有相同键的多个项目。你不会丢失任何数据:

private static IEnumerable<KeyValuePair<string, object>> FromCookies(HttpCookieCollection cc)
        {
            return (from string cookie in cc.AllKeys select new KeyValuePair<string,object>(cookie, cc[cookie]));
        }