Linq 代码重构



请帮助我使用 Linq 重构此代码。如何使用"位置"和"列表"仅使用一次?感谢帮助

private IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address,int? age)       
{
    var ans = new List<SomeClass>();         
    if (!String.IsNullOrEmpty(name))
        ans = aaa.Where(x => x.name.equal(name)).ToList();
    if (!String.IsNullOrEmpty(company))
        ans = ans.Where(x => x.company.equal(company)).ToList();
    if (!String.IsNullOrEmpty(address))
        ans = ans.Where(x => x.address.equal(address)).ToList();
    if (age.HasValue)
        ans = ans.Where(x => x.age == age.Value).ToList();
    return ans;
}

你可以使用这个:

var ans = aaa.Where( x => ( string.IsNullOrEmpty(name)
                            || x.name.equal(name)
                          )
                          &&
                          ( string.IsNullOrEmpty(company)
                            || x.company.equal(company)
                          )
                          &&
                          ( string.IsNullOrEmpty(address)
                            || x.address.equal(address)
                          )
                          &&
                          ( !age.HasValue
                            || x.age == age.Value
                          )
                   );

只是在这里添加另一个答案。为什么要创建一个列表,你的输入是IEnumerable的,所以你的输出是相同的吗?

private IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address, int? age)
{
    if (!String.IsNullOrEmpty(name))
        aaa = aaa.Where(x => x.name.Equals(name));
    if (!String.IsNullOrEmpty(company))
        aaa = aaa.Where(x => x.company.Equals(company));
    if (!String.IsNullOrEmpty(address))
        aaa = aaa.Where(x => x.address.Equals(address));
    if (age.HasValue)
        aaa = aaa.Where(x => x.age == age.Value);
    return aaa;
}

您可以放弃对ToList的所有调用。如果没有这些调用,组合筛选将以您不需要关心的延迟方式执行。

如果您确实想要影响执行筛选的时间(或确保结果基于调用Filteraaa的快照,并且在以后aaa更改时不会更改),请将最后一行更改为

return ans.ToArray();

(这里可能不需要列表;返回的值无论如何都键入IEnumerable<SomeClass>,调用方不应期望能够直接修改(添加/删除项目)返回的对象。

因此,完整的代码将如下所示:

private IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address,int? age)       
{
    IEnumerable<SomeClass> ans = new SomeClass[0];
    if (!String.IsNullOrEmpty(name))
        ans = aaa.Where(x => x.name.Equals(name));
    if (!String.IsNullOrEmpty(company))
        ans = ans.Where(x => x.company.Equals(company));
    if (!String.IsNullOrEmpty(address))
        ans = ans.Where(x => x.address.Equals(address));
    if (age.HasValue)
        ans = ans.Where(x => x.age == age.Value);
    return ans.ToArray();
}

正如其他答案所表明的那样,也可以将所有Where调用合并为一个,尽管坚持原始的ifWhere链非常清楚地显示了它的作用,这对于组合解决方案可能不正确。

我对这个主题的两分钱:

  1. 我认为您不需要将该方法简化为一个Where子句,因为如果您保持这种方式,您以后可以轻松地添加新的过滤器参数,并且您的代码将非常可读。
  2. 您无需指定ToList()
  3. 与其考虑使用String.IsNullOrWhiteSpace()而不是String.IsNullOrEmpty() .这样,如果提供了非空但空格的字符串,则不会筛选出实体。
  4. 与其考虑使用x.name.Equals(name)不如考虑在适当的情况下使用x.name.Equals(name, StringComparison.InvariantCultureIgnoreCase)

你可以做这样的事情:

var ans = aaa.Where(x => !string.IsNullOrEmpty(name) ? x.name.equal(name) : false).ToList()
             .Union(aaa.Where(x => !string.IsNullOrEmpty(company) ? x.company.equal(company) : false).ToList())
             .Union(aaa.Where(x => !string.IsNullOrEmpty(address) ? x.address.equal(address) : false).ToList());
ans = ans.Where(x => age.HasValue ? x.age == age.Value : true).ToList();

你应该尝试这样的事情:

private static IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address, int? age)
{
        var ans = aaa.Where(x => !String.IsNullOrEmpty(name) ? x.Name.Equals(name) : true)
                 .Where(x => !String.IsNullOrEmpty(company) ? x.Company.Equals(company) : true
                     && !String.IsNullOrEmpty(address) ? x.Address.Equals(address) : true
                     && age.HasValue ? x.Age == age.Value : true);

        return ans;
} 

但请注意,在您的代码中,如果 "name" 参数为空,则始终返回 0 结果。

最新更新