选择List
。每个Car
都有一个唯一的索引来标识它,例如RegNumber
,然后是另一个描述它的属性 - 例如Color
。
我想
- 检查该集合中是否有一辆 RegNumber 5 的汽车(
- 如果有),如果没有,则更改颜色
- ,为该汽车添加一个新项目,
- 保存列表
这是我目前正在执行的方式,我正在询问是否有更好、更有效的方法来做到这一点?
Car car = CarsForSale.Find(c => c.RegNumber == 5);
if (car != null)
{
foreach (Car car in CarsForSale)
{
if (car.RegNumber == 5)
{
car.Color = "Red";
break;
}
}
}
else
{
CarsForSale.Add(new Car(5, "Red"));
}
Save(CarsForSale);
编辑
不存在具有相同注册的多辆汽车 - 正如问题中所述,注册编号是唯一的。
无论如何,这实际上只是一个完全愚蠢的时刻,代码审查会发现。感谢您的所有答复,也感谢您没有嘲笑我明显愚蠢的问题。当然,从集合返回的项目/元素是一个引用,因此绝对不需要再次遍历列表......我想是时候把我的头撞到墙上了。
Take List<Car>
. Each Car
has a unique index identifying it, say RegNumber
and then another property describing it - say Color
for example.
I want to
- check if the collection has a car with RegNumber 5
- if it does, change the color
- if it doesn't, add a new item for that car
- save the list
This is the way I am currently doing it and I'm asking if there is a better, more efficient way of doing this?
Car car = CarsForSale.Find(c => c.RegNumber == 5);
if (car != null)
{
foreach (Car car in CarsForSale)
{
if (car.RegNumber == 5)
{
car.Color = "Red";
break;
}
}
}
else
{
CarsForSale.Add(new Car(5, "Red"));
}
Save(CarsForSale);
EDIT
There are not multiple cars with the same reg - the RegNumber is unique as stated in the question.
This was really just a total dumb@ss moment here anyway that a code review would have spotted. Thanks for all the replies and for not mocking my clearly stoopid question. Of course the item/element returned from the collection is a reference so there is absolutely no need to iterate through the list again...time to go bang my head against a wall I think.
发布评论
评论(5)
首先,您不需要在循环中测试
car.RegNumber == 5
- 您已经从语句中找到了第一辆符合此条件的汽车:事实上,您的整个循环是多余的,你可以这样:
除非你想找到所有
RegNumber
等于 5 的汽车,在这种情况下你的第一行是不正确的,因为它只会找到第一辆符合条件的汽车。要找到您想要的所有汽车,请执行以下操作:使用原始代码,编译器应该警告您循环中
car
的重新定义将隐藏原始定义(我引用的那个) 。Well first off you don't need your test for
car.RegNumber == 5
in the loop - you've already found the first car that match this criterion from your statement:In fact your whole loop is redundant, you can just have:
Unless you want to find all cars that have
RegNumber
equal to 5, in which case your first line is incorrect as that will only find the first car that matches the criteria. To find all the cars you want something along these lines:With your original code the compiler should have warned you that the redefinition of
car
in the loop would hide the original definition (the one I've quoted).当你已经有了结果时,为什么还要重新遍历列表呢?
这将实现相同的结果:
CarsForSale
的Find
方法的结果,如果返回结果,将是引用类型,这意味着对的任何更改car
也会更改CarsForSale
中的项目。我猜您认为Find
的结果会与CarsForSale
中的实际项目断开连接,因此出现不必要的 foreach 循环?Why are you re-iterating through the list when you already have a result?
This will achieve the same outcome:
The result from the
Find
method ofCarsForSale
, if it returns a result, will be a reference type, which means any changes tocar
will change the item inCarsForSale
as well. I'm guessing you thought that the result fromFind
would be disconnected from the actual item inCarsForSale
, hence the unnecessary foreach loop?更新
为了回应此评论,您留下了其他几个答案:
如果多辆车可能具有相同的
RegNumber
,则调用Find
不是正确的方法。Find
只是枚举列表以查找匹配项;你最好跳过它并保留你的foreach
循环。但是,您可以通过使用
Where
来使代码更加简洁:原始答案
整个
foreach
循环是多余的:您基本上正在做与已经完成的相同的工作调用查找
。因此代码可以简化:
也就是说,如果您要通过
RegNumber
在List
中查找汽车,那么使用是有意义的字典
而不是List
:Update
In response to this comment you've left on a couple of other answers:
If it's possible for multiple cars to have the same
RegNumber
, then callingFind
is not the right approach.Find
is just enumerating over the list to find a match; you'd be better off skipping it and keeping yourforeach
loop.You could, however, make your code more concise by using
Where
instead:Original answer
That whole
foreach
loop is redundant: you're basically doing the same work you already did by callingFind
.So the code can be simplified:
That said, if you're looking up cars in your
List<Car>
byRegNumber
, it would make sense to use aDictionary<int, Car>
instead of aList<Car>
:一旦您从 LINQ 语句中找到了要查找的汽车,就无需循环返回集合来查找匹配项:
或者如果将有多个具有相同 RegNumber 的汽车:
Once you have the car you're looking for from the LINQ statement, there's no need to loop back through the collection to find the match:
Or if there are going to be multiple Cars with the same RegNumber:
正如 Dan 已经提到的,如果您有一个独特的属性,您应该将其用作
字典
。因为检查字典中是否有某项内容是 O(1) 操作,而在列表中,在最坏的情况下它只是 O(n)(现在假设您的列表中有 100 万辆汽车)。
汽车类的虚拟实现:
您使用字典的问题是,因为您想明确地告诉钥匙是什么(您汽车的 RegNum 属性),但您也可以使用 < a href="http://msdn.microsoft.com/en-us/library/bb359438.aspx" rel="nofollow noreferrer">
Hashset
如果您的 Car 对象会正确实现Equals()
和GetHashCode()
但这比您想象的要复杂一些。可以在Essentials C#一书中找到很好的解释。So as Dan already mentioned, if you have a unique property you should use it as a key within a
Dictionary<TKey, TValue>
.Cause checking if something is within a Dictionary is an O(1) operation, while within a List it is just O(n) in the worst case (and now imagine you have 1 million cars within your list).
Dummy implementation of the car class:
The problem why you are using a Dictionary is, cause you want to explicitly tell what the key is (the RegNum property of your car), but you could also use a
Hashset<T>
if your Car object would correctly implementEquals()
andGetHashCode()
but this is a little more complex than you might think. A good explanation can be found in the Essentials C# book.