需要一个允许重复密钥的数据结构

时间:2015-05-14 19:29:56

标签: c#

我的行数据如下所示:

(汽车,颜色,年龄)

例如:

福特,红色,4
丰田,绿色,3
福特,蓝色,2

我需要循环遍历这些数据行并在提交存储过程之前执行验证。在这种情况下,如果有多个相同类型的汽车,我需要确保颜色不同。所以上面的例子是允许的,但这个例子不会:

福特,红色,4
丰田,绿色,3
福特,红色,2

我如何在C#中做到这一点。我尝试使用字典,但它不允许重复键。列表似乎也不正确?可以提供任何方向吗?感谢。

3 个答案:

答案 0 :(得分:10)

你实际上没有重复的键,你只需要一个由两个值(一个复合键)组成的键,特别是你的值是汽车和颜色。因此,您需要一个表示汽车/颜色对的对象,并且基于这两个值实现相等。

这意味着您不需要不同的数据结构,Dictionary很好,您只需要提供一个合适的类型作为该字典的键。无论是汽车还是单独作为钥匙的颜色都不能实现你想要的东西。

你可以写自己的;只是一个具有两个属性和适当的Equals/GetHashCode覆盖的类,如果这是您在应用程序的多个位置或从足够大的范围使用的东西,那么您应该这样做。如果您仅在有限的本地化范围内使用此功能,则可以使用Tuple<Car, Color>作为词典键。

答案 1 :(得分:0)

如果Servy's answer不适用于你,而你真的只是开车(例如你可能有多辆相同颜色的车)。

内置的类型与ReadOnlyDictionary<Tkey, IEnumerable<TValue>>的行为类似,其中可枚举保存碰撞,它是ILookup

构建一个的最简单方法是在LINQ中使用.ToLookup(扩展方法。

class Row
{
    public CarEnum Car {get; set;}
    public string Color {get; set;}
    public int Age {get; set;
}


void Validate(List<Row> rows)
{
   //I did not use "var" to make it more obvious what is going on, in production code I would use "var".
   ILookup<CarEnum, Row> rowLookup = rows.ToLookup((row)=>row.Car);

   foreach(IGrouping<CarEnum, Row> carKey in rowLookup)
   {
       //This loop would loop once for Ford, once for Toyota

       foreach(Row row in carKey)
       {
           //This loop would loop twice in the Ford iteration and lope once in the Toyota iteration. 
           DoValidate(row);
       }
   }
}

答案 2 :(得分:-1)

另一个解决方案是使用GroupBy表达式查找重复项:

public void Validate(List<Row> rows)
{
    var sameCarColorMoreThanOne = rows.GroupBy(ks => new { ks.Car, ks.Color })
                                      .Select(s => new { s.Key, Count = s.Count() })
                                      .Where(p => p.Count > 1);
    if (sameCarColorMoreThanOne.Any())
        throw new ExceptionWithListOfDuplicateKeys(sameCarColorMoreThanOne.Select(s => new Tuple<string, string>(s.Key.Car, s.Key.Color)).ToList());
}

ExceptionWithListOfDuplicateKeys只是一些想法的异常类型,其中包含违规汽车/颜色组合的元组列表