具有多个子字符串的C#字符串搜索

时间:2018-11-16 18:41:36

标签: c# string search

所以我正在为资源列表创建过滤器,其中一个过滤器是Name属性(字符串)。

作为一个(愚蠢的)示例:资源名称为“大红色/方形表”,过滤器为“红色表”,它应该是有效的资源

这是我用很少的时间就能想到的:

static void ApplyNameFilter(ref ApplicationViewModel model, string filter)
{
    if (string.IsNullOrEmpty(filter) || filter == "") return;
    char[] separators = {' ', ',', '.', '/', '\\', '|', '_', '-'};
    var validResources = new List<ResourceModel>();

    foreach (var resource in model.ResourcesViewModel.Resources)
    {
        var filterSubstrings =
            filter
            .ToLower()
            .Split(separators)
            .ToList();

        var resourceSubstrings =
            resource.Name
            .ToLower()
            .Split(separators)
            .ToList();

        resourceSubstrings.ForEach(substring => {
            if (filterSubstrings.Contains(substring))
                filterSubstrings.RemoveAll(sub => sub == substring);
        });

        if (filterSubstrings.Count == 0)
            validResources.Add(resource);
    }

    model.ResourcesViewModel.Resources = validResources;
}

我应该采用其他方法吗?

编辑: 最后,直到我弄清楚RegEx

static void ApplyNameFilter(ref ApplicationViewModel model, string filter)
{
    if (string.IsNullOrEmpty(filter)) return;

    char[] separators = {' ', ',', '.', '/', '\\', '|', '_', '-'};
    var filterSubstrings =
        filter
            .ToLower()
            .Split(separators)
            .ToList();

    var validResources = model.ResourcesViewModel.Resources
        .Where(resource => filterSubstrings.All(fs => resource.Name.ToLower().Contains(fs)))
        .ToList();

    model.ResourcesViewModel.Resources = validResources;
}    

1 个答案:

答案 0 :(得分:2)

您可以使用LINQ使其更加简洁(可能更快,因为您正在创建List并不必要地在每个资源上删除元素,尽管非LINQ解决方案甚至可以更快)。

var validResources = model.ResourcesViewModel.Resources
                        .Where(resource => {
                            var resourceSubstrings = resource.Name.ToLower().Split(separators).ToHashSet();
                            return filterSubstrings.All(fs => resourceSubstrings.Contains(fs));
                        })
                        .ToList();

如果您愿意接受Name内的所有过滤器子字符串而与separators无关,则可以简化为:

var validResources = model.ResourcesViewModel.Resources
                        .Where(resource => filterSubstrings.All(fs => resource.Name.ToLower().Contains(fs)))
                        .ToList();