我需要检查所有定义是否包含某些特定数据。除了GroupBy返回空集合的情况外,它工作正常。
var exist = dbContext.Definitions
.Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
.GroupBy(x => x.PropertyTypeId)
.All(...some condition...);
如何重写这样所有All会在空集合上返回false?
更新: 它是一个LINQ to SQL,我想在单个调用中执行它。
UPDATE2: 我认为这有效:
var exist = dbContext.Definitions
.Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
.GroupBy(x => x.PropertyTypeId)
.Count(x => x
.All(...some condition...)) == propertyTypeIds.Count;
答案 0 :(得分:12)
如果你正在使用LINQ to Objects,我只会编写自己的扩展方法。我的Edulinq project包含All
的示例代码,并且调整非常简单:
public static bool AnyAndAll<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (predicate == null)
{
throw new ArgumentNullException(nameof(predicate));
}
bool any = false;
foreach (TSource item in source)
{
any = true;
if (!predicate(item))
{
return false;
}
}
return any;
}
这可以避免多次评估输入。
答案 1 :(得分:5)
您可以使用Aggregate
执行此操作,方法如下:
.Aggregate(new {exists = 0, matches = 0}, (a, g) =>
new {exists = a.exists + 1, matches = a.matches + g > 10 ? 1 : 0})
(此处g > 10
是我的测试)
然后是exists
大于零且exists
和matches
具有相同值的简单逻辑。
这可以避免两次运行整个查询。
答案 2 :(得分:4)
您可以使用DefaultIfEmpty
扩展方法,并调整some condition
,以便评估null
至false
。
var exist = definitions
.Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
.GroupBy(x => x.PropertyTypeId)
.DefaultIfEmpty()
.All(...some condition...));
答案 3 :(得分:1)
嗯,你可以分两步完成:
$ cap production ssh:doctor --trace
** Invoke production (first_time)
** Execute production
** Invoke load:defaults (first_time)
** Execute load:defaults
** Invoke bundler:map_bins (first_time)
** Execute bundler:map_bins
** Invoke deploy:set_rails_env (first_time)
** Execute deploy:set_rails_env
** Invoke deploy:set_linked_dirs (first_time)
** Execute deploy:set_linked_dirs
** Invoke deploy:set_rails_env
** Invoke rbenv:validate (first_time)
** Execute rbenv:validate
cap aborted!
NoMethodError: undefined method `on' for main:Object
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/capistrano-rbenv-2.0.4/lib/capistrano/tasks/rbenv.rake:3:in `block (2 levels) in <top (required)>'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:248:in `block in execute'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:243:in `each'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:243:in `execute'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:187:in `block in invoke_with_call_chain'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:180:in `invoke_with_call_chain'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:173:in `invoke'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/capistrano-3.2.1/lib/capistrano/dsl/task_enhancements.rb:12:in `block in after'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:248:in `block in execute'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:243:in `each'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:243:in `execute'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:187:in `block in invoke_with_call_chain'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:180:in `invoke_with_call_chain'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/task.rb:173:in `invoke'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:152:in `invoke_task'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:108:in `block (2 levels) in top_level'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:108:in `each'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:108:in `block in top_level'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:117:in `run_with_threads'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:102:in `top_level'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:80:in `block in run'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:178:in `standard_exception_handling'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rake-11.2.2/lib/rake/application.rb:77:in `run'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/capistrano-3.2.1/lib/capistrano/application.rb:15:in `run'
/Users/admin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/capistrano-3.2.1/bin/cap:3:in `<top (required)>'
/Users/admin/.rbenv/versions/2.3.1/bin/cap:23:in `load'
/Users/admin/.rbenv/versions/2.3.1/bin/cap:23:in `<main>'
Tasks: TOP => rbenv:validate
答案 4 :(得分:1)
编辑:第一个答案不起作用。
如果您稍微重新排列查询,则可以使用DefaultIfEmpty
而无需更改条件:
var exist = dbContext.Definitions
.Where(x => propertyTypeIds.Contains(x.PropertyTypeId)
&& x.CountryId == countryId)
.GroupBy(x => x.PropertyTypeId);
// apply the condition to all entries,
// resulting in sequence of bools (or empty),
// to permit the next step
.Select(...some condition...)
//if seq is empty, add `false`
.DefaultIfEmpty(false)
//All with identity function to apply the query and calculate result
.All(b => b)
);
答案 5 :(得分:1)
这是另一个技巧:
var exist = dbContext.Definitions
.Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
.GroupBy(x => x.PropertyTypeId)
.Min(some_condition ? (int?)1 : 0) == 1;
它利用上述Min<int?>
方法返回的事实:
(A)
null
当集合为空时 (B)0
如果某个元素的条件不满意 (C)1
如果所有元素都满足条件
所以我们使用可空值比较规则来简单检查(C)的结果。
答案 6 :(得分:0)
编写自己的扩展方法怎么样? (我很确定你会更好地命名)
public static bool NotEmptyAll<T>(
this IEnumerable<T> collection,
Func<T, bool> predicate)
{
return collection != null
&& collection.Any()
&& collection.All(predicate);
}
然后调用它而不是All
var exist = definitions.Where(
x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId)
.GroupBy(x => x.PropertyTypeId)
.NotEmptyAll(
...some condition...));
答案 7 :(得分:0)
这是All
的替代方法,如果集合为空,则返回false
:
var collection = Enumerable.Range(0, 0); //empty collection
collection
.Select(IsValid)
.DefaultIfEmpty(false)
.All(b => b);
或作为扩展方法:
public static bool AnyAndAll<T>(IEnumerable<T> collection, Func<T, bool> predicate) =>
collection
.Select(predicate)
.DefaultIfEmpty(false)
.All(b => b);