我的行数据如下所示:
(汽车,颜色,年龄)
例如:
福特,红色,4
丰田,绿色,3
福特,蓝色,2
我需要循环遍历这些数据行并在提交存储过程之前执行验证。在这种情况下,如果有多个相同类型的汽车,我需要确保颜色不同。所以上面的例子是允许的,但这个例子不会:
福特,红色,4
丰田,绿色,3
福特,红色,2
我如何在C#中做到这一点。我尝试使用字典,但它不允许重复键。列表似乎也不正确?可以提供任何方向吗?感谢。
答案 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只是一些想法的异常类型,其中包含违规汽车/颜色组合的元组列表