搜索功能在找到结果后停止查看

时间:2014-07-25 17:14:01

标签: c# refactoring

我正在研究一个简单的搜索功能。用户输入关键字request.Keyword并期望搜索功能“找出”他想要的,然后使用关键字在该集合中进行搜索。 的三个选项是NameNumberCode

我首先提出的是以下

// Keyword filter
if (!string.IsNullOrWhiteSpace(request.Keyword))
{
    var searchResults = _items.Where(x => x.Name.Contains(request.Keyword)).ToList();
    if (searchResults.Any()) _items = searchResults;

    searchResults= _items.Where(x => x.Number == request.Keyword).ToList();
    if (searchResults.Any()) _items = searchResults;

    searchResults= _items.Where(x => x.Code == request.Keyword).ToList();
    if (searchResults.Any()) _items = searchResults;
}

这里的问题是程序在找到搜索结果后继续if - 块并继续搜索其他集合。但是既然我们已经有了搜索结果,那就没必要了。

第二个问题是,当找不到搜索结果时_items保持不变。但事实上,在这种情况下,用户希望它是空的。

在代码中,我想要实现的东西看起来就像这样美:

// Keyword filter
if (!string.IsNullOrWhiteSpace(request.Keyword))
{
    var searchResults = _items.Where(x => x.Name.Contains(request.Keyword)).ToList();
    if (searchResults.Any())
    {
        _items = searchResults;
    }
    else
    {
        searchResults = _items.Where(x => x.Number == request.Keyword).ToList();
        if (searchResults.Any())
        {
            _items = searchResults;
        }
        else
        {
            searchResults = _items.Where(x => x.Code == request.Keyword).ToList();
            if (searchResults.Any())
            {
                _items = searchResults;
            }
            else
            {
                // Keyword was set, but no result was found.
                _items.Clear();
            }
        }
    }
}

正如您所看到的,嵌套非常糟糕(这是简化的代码)。添加新的收藏会使情况变得更糟......

如何通过(或多或少)干净的代码实现这一目标?

3 个答案:

答案 0 :(得分:2)

方式1。

// Keyword filter
var keyword = request.Keyword;
if (!string.IsNullOrWhiteSpace(keyword))
{    
    var searchResults = _items.Where(x => x.Name.Contains(keyword)).ToList();
    if (searchResults.Length == 0)
        searchResults = _items.Where(x => x.Number == keyword).ToList();
    if (searchResults.Length == 0)
        searchResults = _items.Where(x => x.Code == keyword).ToList();      
    if (searchResults.Length == 0)
        _items.Clear();
    else
        _items = searchResults;
}

方式2。

public static List<Item> Search(List<Item> items, Predicate<Item> predicate)
{
  var searchResults = items.Where(predicate).ToList();
  return searchResults.Any() ? searchResults : null;
}

// Keyword filter
var keyword = request.Keyword;
if (!string.IsNullOrWhiteSpace(keyword))
{    
    _items = 
      Search(_items, x => x.Name.Contains(keyword)) ??
      Search(_items, x => x.Number == keyword) ??
      Search(_items, x => x.Code == keyword) ??
      new List<Item>();
}

答案 1 :(得分:1)

如果您提取此方法以便返回结果而不是继续,则可以跳过所有else

// Keyword filter
if (string.IsNullOrWhiteSpace(request.Keyword)) 
{
    return emptyList;
}
var searchResults = _items.Where(x => x.Name.Contains(request.Keyword)).ToList();
if (searchResults.Any())
{
    return searchResults;
}
searchResults = _items.Where(x => x.Number == request.Keyword).ToList();
if (searchResults.Any())
{
    return searchResults;
}
searchResults = _items.Where(x => x.Code == request.Keyword).ToList();
if (searchResults.Any())
{
    return searchResults;
}

return emptyList;

答案 2 :(得分:1)

如果您的请求符合NameNumberCode中的任何一项,并且如果您需要所有这些请求,您的代码可以简化如下。

var searchResults = _items.Where(x => x.Name.Contains(request.Keyword) ||
                                      x.Number == request.Keyword      ||
                                      x.Code == request.Keyword)
                          .ToList();

if(!searchResults.Any())
{
    _items.Clear();
}