var tmpProjection = myCollection.ToLookup(t => t.SomeBoolValue);
var listOneFinal = tmpProjection[true];
var listTwo = tmpProjection[false];
第一个问题,有没有办法以较短的方式将它分配给listOne和listTwo,我知道我在这里迂腐,......只是问。
现在,
var listThree = listTwo.ToLookup(t => t.SomeOtherBoolValue);
var listFourFinal = listThree[false];
var listFiveFinal = listThree[true];
所以在这种情况下,我只需要(最终)listOneFinal,listFourFinal和listFiveFinal - 但我正在创建这些临时内容......有没有办法减少这种情况。
我只是谈论代码而不是性能或代码的关键性。
答案 0 :(得分:3)
Lookup<int, T> myLookup = myCollection
.ToLookup(t =>
t.someBoolValue ? 1 :
t.someOtherBoolValue ? 4 :
5
);
var listOne = myLookup[1];
var listFour = myLookup[4];
var listFive = myLookup[5];
答案 1 :(得分:1)
您可以在较少的语句中执行此操作,但由于您需要使用3个值结束操作,因此至少需要3个分配。您的代码非常易读,不会牺牲“智能”的可读性并减少更少的语句。话虽这么说,这是一个3语句版本;如果集合很小(在大型集合中你自己的版本会表现得更好,因为这个版本在集合中多次迭代),这将很有效:
var listOneFinal = myCollection.Where(t => t.SomeBoolValue);
var listFourFinal = myCollection.Where(t => !t.SomeBoolValue && !t.SomeOtherBoolValue);
var listFiveFinal = myCollection.Where(t => !t.SomeBoolValue && t.SomeOtherBoolValue);
根据您的实际使用情况,上述内容可能更具可读性。
答案 2 :(得分:0)
我认为你所拥有的东西已经非常好了,说实话。
如果您只想减少语句的数量,我怀疑您可以做得更好:
var listOneFinal = myCollection.Where(t => t.SomeBoolValue);
var listFourFinal = myCollection.Where(t => !t.SomeBoolValue && !t.SomeOtherBoolValue);
var listFiveFinal = myCollection.Where(t => !t.SomeBoolValue && t.SomeOtherBoolValue);
或者也许:
var predicates = new Func<MyClass,bool>[]{ t => t.SomeBoolValue, t => t.SomeOtherBoolValue};
var listOneFinal = myCollection.Where(predicates.First());
var listFourFinal = myCollection.Where(t => !predicates.Any(p => p(t)));
var listFiveFinal = myCollection.Where(t => !predicates[0](t) && predicates[1](t));
(如果需要,请在每个查询上调用ToList()
)
但实际上,我更喜欢你的技术,我提供的代码不是特别易读或有效。
您可能想要考虑仅存储2个查找而不是每个列表,并在必要时内联每个“最终查找”,因为调用Lookup[key]
很便宜。因此,只要您需要listFourFinal
,只需调用listThree[false].
更好的变量名称显然会有所帮助。
答案 3 :(得分:0)
如果您发现自己经常这样做,可以编写一个函数来执行此操作。对于布尔值ToLookup
,我们可以使用C#的out parameters来返回多个值。
public static void Dichotomize<T>(this IEnumerable<T> source,
Func<T,bool> keySelector,
out IEnumerable<T> affirmative,
out IEnumerable<T> negative) {
if (source == null) throw new ArgumentNullException("source");
if (keySelector == null) throw new ArgumentNullException("keySelector");
var affirmativeList = new List<T>();
var negativeList = new List<T>();
foreach (var element in source) {
(keySelector(element) ? affirmativeList : negativeList).Add(element);
}
affirmative = affirmativeList.AsReadOnly();
negative = negativeList.AsReadOnly();
}
现在我们可以做到:
IEnumerable<T> listOneFinal, listTwo, listFourFinal, listFiveFinal;
myCollection.Dichotomize(t => t.SomeBoolValue, out listOneFinal, out listTwo);
listTwo.Dichotomize(t => t.SomeOtherBoolValue, out listFiveFinal, out listFourFinal);