需要一个允许重复键的数据结构
本文关键字:许重复 数据结构 一个 | 更新日期: 2023-09-27 17:49:19
我有数据行,看起来像这样:
(汽车,颜色,年龄)例如
:
福特,红色,4
丰田,绿色,3
福特、蓝色、2
我需要遍历这些数据行,并在提交给存储过程之前执行验证。在这种情况下,如果有不止一辆相同类型的汽车,我需要确保颜色不同。所以上面的例子是允许的,但是这个例子不允许:
福特,红色,4
丰田,绿色,3
福特,红2
我如何在c#中做到这一点。我试过用字典,但它不允许重复的键。列表似乎也不是正确的选择?有人能指点一下吗?谢谢。
实际上没有重复的键,您只是有一个由两个值组成的键(复合键),具体来说,您的值是汽车和颜色。因此,您需要一个表示汽车/颜色对的对象,并根据这两个值实现相等。
这意味着你不需要一个不同的数据结构,Dictionary
很好,你只需要想出一个合适的类型作为字典的键。单凭一辆车或一种颜色都不能达到你想要的效果。
你可以自己写;只是一个类,具有两个属性和适当的Equals/GetHashCode
覆盖,如果这是您在应用程序的多个地方或在足够大的范围内使用的东西,您应该这样做。如果你只在有限的局部范围内使用它,你可以使用Tuple<Car, Color>
作为你的字典键。
如果Servy的答案不适用于您,并且您确实只是在汽车上键入了键(例如,您可能有多辆相同颜色的汽车)。
有一个内置的类型,其行为类似于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);
}
}
}
另一个解决方案是使用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只是一些想出的异常类型,它包含违规汽车/颜色组合的元组列表