3

我有一个不好的要求要做;无论如何,我必须在我的应用程序中实现它。

我有一Track堂课

public class Track
{
    public string Name { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

我有一些测试数据

List<Track> Records = new List<Track>
{ 
    new Track { City = "a", Name = "a",  Country = "i" }, // Track 1
    new Track { City = "b", Name = "b",  Country = "i" }, // Track 2
    new Track { City = "a", Name = null, Country = "J" }, // Track 3
    new Track { City = "c", Name = "a",  Country = "J" }, // Track 4
    new Track { City = "b", Name = "a",  Country = null}, // Track 5
};

要求是我应该Records根据传递的值查询数据。如果有任何属性,null则搜索条件应忽略该属性。它应该根据NonNull属性进行查询。

示例

If i query for City = a, Name = "b", Country = "i" then Result is: Track 1 & Track 3
If i query for City = c, Name = "p", Country = "w" then Result is: Track 4

Name&在&中有空Country值。所以它会在搜索中忽略。希望清楚Track 3Track 5

我终于明白了以下逻辑

var filterRecords = new List<Track>();
if (!Records.Any(t => string.IsNullOrWhiteSpace(t.City)))
{
    filterRecords = Records.Where(c => c.City == _city).ToList();  // Here _city is the method parameter.. assume "a"
}

if (!Records.Any(t => string.IsNullOrWhiteSpace(t.Country)))
{
    filterRecords = filterRecords.Where(c => c.City == _country).ToList();  // Here _country is the method parameter.. assume "c"
}

Track类有 12 个属性。像上面那样检查 12 次不是好兆头。我想通过使用LINQ或任何其他简单的方法来实现这一点。

请问有什么建议吗?

4

5 回答 5

6

我想到的最佳解决方案是构建聚合过滤器(您可以为此使用 Track 对象,因为它已经具有过滤集合的所有可能属性,并且它们可以为空):

Track filter = records.Aggregate(
    new Track() { City = _city, Country = _country, Name = _name },
    (f, t) => new Track()
    {
        City = String.IsNullOrEmpty(t.City) ? null : f.City, 
        Country = String.IsNullOrEmpty(t.Country) ? null : f.Country,
        Name = String.IsNullOrEmpty(t.Name) ? null : f.Name
    },
    f => f);

这将只需要对集合进行一次迭代即可定义哪些字段为空。然后只需将过滤器应用于您的记录:

var query = from t in Records
            where (filter.City == null || t.City == filter.City) &&
                    (filter.Country == null || t.Country == filter.Country) &&
                    (filter.Name == null || t.Name == filter.Name)
            select t;
于 2012-11-08T17:06:48.647 回答
0

您可以轻松地将这些表达式链接在一起以创建如下所示的内容。枚举记录 X 次会减慢您的代码速度。例子:

var actualResult = Records
       .Where(x => x.City == _city || string.IsNullOrEmpty(x.City))
       .Where(x => x.Country == _country || string.IsNullOrEmpty(x.Country))
       /// .... and so on
       .ToList()

现在,如果您不仅要编写 12 行代码,还有更复杂的解决方案涉及反射和映射,但在这种情况下并不真正需要。如果您的财产数量很大,那么也许值得。但是 12 个属性足够小,对我来说没有太多代码气味。

于 2012-11-08T16:46:28.500 回答
0

如果我理解的话,应该很简单:

var results = Records.Select(p => p.City != null && 
              p.Country != null && 
              p.Name != null).ToList();
于 2012-11-08T16:53:23.157 回答
0

返回结果的质量和数量对您来说重要吗?我假设您有处理数量的机制。

您可以在抛出查询之前验证您的搜索关键字。你只关心空值吗?多余的关键字怎么办?我会考虑: 1. 验证关键字 - 12 可以循环。2. 建立搜索关键字强 3. 进行查询

看起来很简单,除非它比您在此处描述的更多。

如果我对您的问题的理解不在预期的方向,请纠正我。

于 2012-11-08T16:56:51.013 回答
-1

像这样的东西

var listRecords = from track in Records
where (track.city == _city && !string.IsEmpyOrNull(track.city)) && 
(track.Name== _name && !string.IsEmpyOrNull(track.Name))
select track;

你可以添加其余的条件

于 2012-11-08T16:48:58.570 回答